bzoj2588 Spoj10628. count on a tree
题目描述
给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。
输入输出格式
输入格式:
第一行两个整数N,M。
第二行有N个整数,其中第i个整数表示点i的权值。
后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
最后M行每行两个整数(u,v,k),表示一组询问。
输出格式:
M行,表示每个询问的答案。
输入输出样例
输入样例#1:
8 5 105 2 9 3 8 5 7 7 1 2 1 3 1 4 3 5 3 6 3 7 4 8 2 5 1 0 5 2 10 5 3 11 5 4 110 8 2
输出样例#1:
2 8 9 105 7
说明
HINT:
N,M<=100000
暴力自重。。。
题解
其实就是个很简单的主席树,只要把在序列上的建树改成在树上建就可以了
虽然我也是今天看到这道题看完题解才知道怎么在树上建主席树
关于路径,可以在树上差分一下用$sum[l]+sum[r]-sum[lca]-sum[lca_fa]$
然后因为要求lca,所以在树剖dfs的时候顺便建一下主席树就好了
具体实现请参考代码
1 //minamoto 2 #include<bits/stdc++.h> 3 #define N 100005 4 #define M 2000005 5 using namespace std; 6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 7 char buf[1<<21],*p1=buf,*p2=buf; 8 inline int read(){ 9 #define num ch-'0' 10 char ch;bool flag=0;int res; 11 while(!isdigit(ch=getc())) 12 (ch=='-')&&(flag=true); 13 for(res=num;isdigit(ch=getc());res=res*10+num); 14 (flag)&&(res=-res); 15 #undef num 16 return res; 17 } 18 int sum[M],L[M],R[M]; 19 int a[N],b[N],rt[N]; 20 int fa[N],sz[N],d[N],ver[N<<1],Next[N<<1],head[N],son[N],top[N]; 21 int n,q,m,cnt=0,tot=0,ans=0; 22 void update(int last,int &now,int l,int r,int x){ 23 sum[now=++cnt]=sum[last]+1; 24 if(l==r) return; 25 int mid=(l+r)>>1; 26 if(x<=mid) R[now]=R[last],update(L[last],L[now],l,mid,x); 27 else L[now]=L[last],update(R[last],R[now],mid+1,r,x); 28 } 29 inline void add(int u,int v){ 30 ver[++tot]=v,Next[tot]=head[u],head[u]=tot; 31 ver[++tot]=u,Next[tot]=head[v],head[v]=tot; 32 } 33 void dfs(int u){ 34 sz[u]=1,d[u]=d[fa[u]]+1; 35 update(rt[fa[u]],rt[u],1,m,a[u]); 36 for(int i=head[u];i;i=Next[i]){ 37 int v=ver[i]; 38 if(v==fa[u]) continue; 39 fa[v]=u,dfs(v); 40 sz[u]+=sz[v]; 41 if(!son[u]||sz[v]>sz[son[u]]) son[u]=v; 42 } 43 } 44 void dfs(int u,int tp){ 45 top[u]=tp; 46 if(!son[u]) return; 47 dfs(son[u],tp); 48 for(int i=head[u];i;i=Next[i]){ 49 int v=ver[i]; 50 if(v==son[u]||v==fa[u]) continue; 51 dfs(v,v); 52 } 53 } 54 int LCA(int x,int y){ 55 while(top[x]!=top[y]) 56 d[top[x]]>=d[top[y]]?x=fa[top[x]]:y=fa[top[y]]; 57 return d[x]>=d[y]?y:x; 58 } 59 int query(int ql,int qr,int lca,int lca_fa,int l,int r,int k){ 60 if(l>=r) return l; 61 int x=sum[L[ql]]+sum[L[qr]]-sum[L[lca]]-sum[L[lca_fa]]; 62 int mid=(l+r)>>1; 63 if(x>=k) return query(L[ql],L[qr],L[lca],L[lca_fa],l,mid,k); 64 else return query(R[ql],R[qr],R[lca],R[lca_fa],mid+1,r,k-x); 65 } 66 int main(){ 67 //freopen("testdata.in","r",stdin); 68 n=read(),q=read(); 69 for(int i=1;i<=n;++i) 70 b[i]=a[i]=read(); 71 sort(b+1,b+1+n); 72 m=unique(b+1,b+1+n)-b-1; 73 for(int i=1;i<=n;++i) 74 a[i]=lower_bound(b+1,b+1+m,a[i])-b; 75 for(int i=1;i<n;++i){ 76 int u=read(),v=read(); 77 add(u,v); 78 } 79 dfs(1),dfs(1,1); 80 while(q--){ 81 int x,y,z,lca; 82 x=read(),y=read(),z=read(); 83 x^=ans,lca=LCA(x,y); 84 ans=b[query(rt[x],rt[y],rt[lca],rt[fa[lca]],1,m,z)]; 85 printf("%d\n",ans); 86 } 87 return 0; 88 }
深深地明白自己的弱小