BZOJ_2588_Spoj 10628. Count on a tree_树剖+主席树
题意:
给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。
分析:
每个结点开线段树,保存到根这段路径上的权值,然后类似树上差分在主席树上求第k小
代码:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define N 100050 int head[N],to[N<<1],nxt[N<<1]; int top[N],fa[N],dep[N],son[N],siz[N],tot,cnt; int n,m,root[N],t[N*50],ls[N*50],rs[N*50],a[N],see; struct A{ int num,id,v; }d[N]; bool cmp1(const A &x,const A &y){return x.num<y.num;} bool cmp2(const A &x,const A &y){return x.id<y.id;} inline void add(int u,int v){ to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt; } void rd(int &x){ int f=1;x=0;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}x*=f; } void dfs1(int x){ siz[x]=1; for(int i=head[x];i;i=nxt[i])if(to[i]!=fa[x]){ fa[to[i]]=x;dep[to[i]]=dep[x]+1; dfs1(to[i]); siz[x]+=siz[to[i]]; if(siz[to[i]]>siz[son[x]])son[x]=to[i]; } } void dfs2(int x,int t){ top[x]=t; if(son[x])dfs2(son[x],t); for(int i=head[x];i;i=nxt[i])if(to[i]!=fa[x]&&to[i]!=son[x])dfs2(to[i],to[i]); } int LCA(int x,int y){ while(top[x]!=top[y]){ if(dep[top[x]]>dep[top[y]])swap(x,y); y=fa[top[y]]; } return dep[x]<dep[y]?x:y; } void insert(int x,int &y,int l,int r,int val){ y=++tot; if(l==r){t[y]=t[x]+1;return ;} int mid=l+r>>1; if(val<=mid) rs[y]=rs[x],insert(ls[x],ls[y],l,mid,val); else ls[y]=ls[x],insert(rs[x],rs[y],mid+1,r,val); t[y]=t[ls[y]]+t[rs[y]]; } int query(int x,int y,int lca,int f,int l,int r,int k){ if(l==r)return a[l]; int mid=l+r>>1,sizls=t[ls[x]]+t[ls[y]]-t[ls[lca]]-t[ls[f]]; if(k<=sizls) return query(ls[x],ls[y],ls[lca],ls[f],l,mid,k); else return query(rs[x],rs[y],rs[lca],rs[f],mid+1,r,k-sizls); } void build(int x){ for(int i=head[x];i;i=nxt[i]){ if(to[i]!=fa[x]){ insert(root[x],root[to[i]],1,n,d[to[i]].v); build(to[i]); } } } int main(){ rd(n);rd(m); int i,x,y,k,j; for(i=1;i<=n;i++) rd(d[i].num),d[i].id=i; sort(d+1,d+n+1,cmp1); d[0].num=-1000000; for(j=0,i=1;i<=n;i++){if(d[i].num!=d[i-1].num)j++;d[i].v=j;a[j]=d[i].num;} sort(d+1,d+n+1,cmp2); for(i=1;i<n;i++) { rd(x);rd(y); add(x,y);add(y,x); } dep[1]=1;fa[1]=0; dfs1(1);dfs2(1,1); int ans=0; //for(i=1;i<=n;i++) insert(root[fa[a[i]]],root[a[i]],minn,maxn,v[a[i]]); insert(root[0],root[1],1,n,d[1].v); build(1); for(i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&k);x^=ans; int lca=LCA(x,y); ans=query(root[x],root[y],root[lca],root[fa[lca]],1,n,k); if(i<m) printf("%d ",ans); else printf("%d",ans); } }