BZOJ 2588: Spoj 10628. Count on a tree 主席树+lca
分析:树上第k小,然后我想说的是主席树并不局限于线性表
详细分析请看http://www.cnblogs.com/rausen/p/4006116.html,讲的很好,
然后因为这个熟悉了主席树,真是神器,强制在线,然后顺便学习了LCA倍增算法
LCA倍增算法是O(nlogn)预处理,然后O(logn)查询,其实和ST是一样的,但是好写啊
/************************************************************** Problem: 2588 User: 96655 Language: C++ Result: Accepted Time:4792 ms Memory:47884 kb ****************************************************************/ #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int N = 1e5+5; const int INF=0x3f3f3f3f; typedef unsigned long long ULL; typedef long long LL; int a[N],c[N],pos[N],n,q,cnt; int root[N],sz; struct Node{ int l,r,v; }o[N*25]; void update(int &rt,int l,int r,int x){ o[++sz]=o[rt],rt=sz; ++o[rt].v; if(l==r)return; int m=(l+r)>>1; if(x<=m)update(o[rt].l,l,m,x); else update(o[rt].r,m+1,r,x); } int d[N],fa[N][20],head[N],tot; struct Edge{ int v,next; }edge[N<<1]; void add(int u,int v){ edge[tot].v=v; edge[tot].next=head[u]; head[u]=tot++; } void dfs(int u,int f){ fa[u][0]=f; d[u]=d[f]+1; update(root[u]=root[f],1,cnt,pos[u]); for(int i=head[u];~i;i=edge[i].next){ int v=edge[i].v; if(v==f)continue; dfs(v,u); } } int lca(int u,int v){ if(d[u]<d[v])swap(u,v); for(int t=d[u]-d[v],i=0;t;t>>=1,++i) if(t&1)u=fa[u][i]; if(u==v)return u; for(int i=19;i>=0;--i){ if(fa[u][i]!=-1&&fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i]; } return fa[u][0]; } int query(int u,int v,int k){ int k1=lca(u,v),k2=fa[k1][0]; u=root[u],v=root[v],k1=root[k1],k2=root[k2]; int l=1,r=cnt; while(l!=r){ int m=(l+r)>>1; int tmp=o[o[u].l].v+o[o[v].l].v-o[o[k1].l].v-o[o[k2].l].v; if(k<=tmp)r=m,u=o[u].l,v=o[v].l,k1=o[k1].l,k2=o[k2].l; else l=m+1,k-=tmp,u=o[u].r,v=o[v].r,k1=o[k1].r,k2=o[k2].r; } return a[l]; } int main() { scanf("%d%d",&n,&q); for(int i=1;i<=n;++i) scanf("%d",&a[i]),c[i]=a[i]; sort(a+1,a+n+1); cnt=unique(a+1,a+1+n)-a-1; for(int i=1;i<=n;++i) pos[i]=lower_bound(a+1,a+1+cnt,c[i])-a; tot=root[0]=sz=0; memset(head,-1,sizeof(head)); memset(fa,-1,sizeof(fa)); for(int i=1;i<n;++i){ int u,v; scanf("%d%d",&u,&v); add(u,v),add(v,u); } dfs(1,0); for(int j=1;(1<<j)<=n;++j) for(int i=1;i<=n;++i) if(fa[i][j-1]!=-1&&i!=1&&j!=0) fa[i][j]=fa[fa[i][j-1]][j-1]; int lastans=0; while(q--){ int u,v,k; scanf("%d%d%d",&u,&v,&k); u^=lastans; printf("%d",lastans=query(u,v,k)); if(q)printf("\n"); } return 0; }