这一题一眼直接树剖 $+$ 主席树秒了,但是我并不想写这么麻烦的东西
所以我就开始琢磨换个简单的做法,发现可以离线,所以就想到了 $dsu\ on\ tree$
然后在想子树第 $k$ 大要怎么维护,感觉好像又要写什么数据结构,突然发现反正都是离线,直接 $sort$ 就完事了
然后就真的完事了,复杂度 $O(n( \log n)^2)$ ,SPOJ 由于电脑年代久远竟然 $T$ 飞了?本机测最大数据就 $0.1s$(为啥我会有数据呢)
在陈立杰神仙的 $ppt$ 里就可以看到对 SPOJ 的吐槽,由于某一题的哈希做法被卡常
(字符串长度只有 $1e5$),使得他 引入(发明?)了后缀自动机,所以现在才有这么多毒瘤后缀自动机毒瘤题...
(上图摘自陈立杰神仙的 $ppt$)
综上, $TLE$ 并不是我算法的问题....
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<vector> using namespace std; typedef long long ll; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } const int N=2e5+7; int fir[N],from[N<<1],to[N<<1],cntt; inline void add(int a,int b) { from[++cntt]=fir[a]; fir[a]=cntt; to[cntt]=b; } int n,m,a[N],ans[N]; int son[N],sz[N],pos[N],cnt; struct poi{ int id,val; poi (int a=0,int b=0) { id=a,val=b; } inline bool operator < (const poi &tmp) const { return val<tmp.val; } }; vector <poi> tmp; struct dat{ int id,k; dat (int a=0,int b=0) { id=a,k=b; } }; vector <dat> Q[N]; void dfs1(int x,int fa) { sz[x]=1; for(int i=fir[x];i;i=from[i]) { int &v=to[i]; if(v==fa) continue; dfs1(v,x); sz[x]+=sz[v]; if(sz[v]>sz[son[x]]) son[x]=v; } } inline void calc(int x) { int len=Q[x].size(); for(int i=0;i<len;i++) ans[Q[x][i].id]=tmp[Q[x][i].k-1].id; } void dfs2(int x,int fa,bool type) { pos[++cnt]=x; int L=cnt; if(!son[x]) { tmp.push_back(poi(x,a[x])); calc(x); if(!type) tmp.clear(); return; } for(int i=fir[x];i;i=from[i]) { int &v=to[i]; if(v==fa||v==son[x]) continue; dfs2(v,x,0); } int R=cnt; dfs2(son[x],x,1); for(int i=L;i<=R;i++) tmp.push_back(poi(pos[i],a[pos[i]])); sort(tmp.begin(),tmp.end()); calc(x); if(!type) tmp.clear(); } int main() { n=read(); for(int i=1;i<=n;i++) a[i]=read(); int u,v; for(int i=1;i<n;i++) { u=read(),v=read(); add(u,v); add(v,u); } m=read(); for(int i=1;i<=m;i++) { u=read(),v=read(); Q[u].push_back(dat(i,v)); } dfs1(1,0); dfs2(1,0,1); for(int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }