BZOJ 2588 Spoj 10628. Count on a tree
题解:主席树,上一层为父亲节点对应的主席树
查询就用 u+v-lca-fa[lca]即可
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=200009; int n,m; int lastans; int v[maxn]; int cntedge; int head[maxn]; int to[maxn<<1],nex[maxn<<1]; void Addedge(int x,int y){ nex[++cntedge]=head[x]; to[cntedge]=y; head[x]=cntedge; } int b[maxn],nn; int root[maxn]; int PTsiz; struct PresidentTree{ int l,r,d,ls,rs; }tree[maxn*20]; void BuildTree(int &now,int l,int r){ now=++PTsiz; tree[now].l=l;tree[now].r=r;tree[now].d=0; if(l==r)return; int mid=(l+r)>>1; BuildTree(tree[now].ls,l,mid); BuildTree(tree[now].rs,mid+1,r); } void Updatapoint(int &now,int pre,int p){ now=++PTsiz; tree[now]=tree[pre]; tree[now].d++; if(tree[now].l==tree[now].r)return; int mid=(tree[now].l+tree[now].r)>>1; if(p<=mid)Updatapoint(tree[now].ls,tree[pre].ls,p); else Updatapoint(tree[now].rs,tree[pre].rs,p); } int Querykth(int x,int y,int z,int w,int k){ if(tree[x].l==tree[x].r)return b[tree[x].l]; int d=tree[tree[x].ls].d+tree[tree[y].ls].d-tree[tree[z].ls].d-tree[tree[w].ls].d; if(k<=d)return Querykth(tree[x].ls,tree[y].ls,tree[z].ls,tree[w].ls,k); else return Querykth(tree[x].rs,tree[y].rs,tree[z].rs,tree[w].rs,k-d); } int f[maxn][20]; int depth[maxn]; void Dfs(int now,int fa){ f[now][0]=fa; depth[now]=depth[fa]+1; int p=lower_bound(b+1,b+1+nn,v[now])-b; Updatapoint(root[now],root[fa],p); for(int i=head[now];i;i=nex[i]){ if(to[i]==fa)continue; Dfs(to[i],now); } } void LCAinit(){ for(int j=1;j<=19;++j){ for(int i=1;i<=n;++i){ f[i][j]=f[f[i][j-1]][j-1]; } } } int Querylca(int u,int v){ if(depth[u]<depth[v])swap(u,v); for(int j=19;j>=0;--j){ if(depth[f[u][j]]>=depth[v])u=f[u][j]; } if(u==v)return u; for(int j=19;j>=0;--j){ if(f[u][j]!=f[v][j]){ u=f[u][j];v=f[v][j]; } } return f[u][0]; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i){ scanf("%d",&v[i]);b[i]=v[i]; } sort(b+1,b+1+n); nn=unique(b+1,b+1+n)-b-1; for(int i=1;i<=n-1;++i){ int x,y;scanf("%d%d",&x,&y); Addedge(x,y);Addedge(y,x); } BuildTree(root[0],1,n); Dfs(1,0); LCAinit(); while(m--){ int u,v,k; scanf("%d%d%d",&u,&v,&k); u^=lastans; int lca=Querylca(u,v); printf("%d",lastans=Querykth(root[u],root[v],root[lca],root[f[lca][0]],k)); if(m!=0)printf("\n"); } return 0; }
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!