【bzoj 2588】Spoj 10628. Count on a tree
2017-12-24 14:04
393 查看
Description
给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。Input
第一行两个整数N,M。 第二行有N个整数,其中第i个整数表示点i的权值。 后面N-1行每行两个整数(x,y),表示点x到点y有一条边。 最后M行每行两个整数(u,v,k),表示一组询问。Output
M行,表示每个询问的答案。最后一个询问不输出换行符
Sample Input
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
Sample Output
2
8
9
105
7
HINT
N,M<=100000 暴力自重。。。 在树上建主席树,统计答案时为避免LCA被减两次,计算sum[x]+sum[y]-sum[lca(x,y)]-sum[fa[lca(x,y)]]。#include<cstdio> #include<algorithm> #include<cstring> #define LL long long using namespace std; const int N=1e5+5; int n,m,tot,x,y,rk,cnte,ind,cnt,temp,lastans; int v ,tmp ,first ,id ,num ,root ; int deep ,fa [20]; struct node{int lc,rc,sum;}tr[N*20]; struct edge{int to,next;}e[N*2]; int read() { int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } void ins(int u,int v){e[++cnte]=(edge){v,first[u]};first[u]=cnte;} void insert(int u,int v){ins(u,v);ins(v,u);} void dfs(int x) { ind++;id[x]=ind;num[ind]=x; for(int i=1;(1<<i)<=deep[x];i++)fa[x][i]=fa[fa[x][i-1]][i-1]; for(int i=first[x];i;i=e[i].next) { if(deep[e[i].to])continue; fa[e[i].to][0]=x;deep[e[i].to]=deep[x]+1;dfs(e[i].to); } } int lca(int ri,int rj) { if(deep[ri]<deep[rj])swap(ri,rj); int d=deep[ri]-deep[rj]; for(int i=0;(1<<i)<=d;i++)if((1<<i)&d)ri=fa[ri][i]; if(ri==rj)return ri; for(int i=17;i>=0;i--) if((1<<i)<=deep[ri]&&fa[ri][i]!=fa[rj][i]) ri=fa[ri][i],rj=fa[rj][i]; return fa[ri][0]; } void update(int &x,int last,int L,int R,int num) { x=++cnt;tr[x].sum=tr[last].sum+1; if(L==R)return; tr[x].lc=tr[last].lc;tr[x].rc=tr[last].rc; int mid=(L+R)>>1; if(num<=mid)update(tr[x].lc,tr[last].lc,L,mid,num); else update(tr[x].rc,tr[last].rc,mid+1,R,num); } int query(int x,int y,int rk) { int a=x,b=y,c=lca(x,y),d=fa[c][0]; a=root[id[x]];b=root[id[b]];c=root[id[c]];d=root[id[d]]; int L=1,R=tot; while(L<R) { int mid=(L+R)>>1; temp=tr[tr[a].lc].sum+tr[tr[b].lc].sum-tr[tr[c].lc].sum-tr[tr[d].lc].sum; if(temp>=rk)R=mid,a=tr[a].lc,b=tr[b].lc,c=tr[c].lc,d=tr[d].lc; else rk-=temp,L=mid+1,a=tr[a].rc,b=tr[b].rc,c=tr[c].rc,d=tr[d].rc; } return tmp[L]; } int main() { n=read();m=read(); for(int i=1;i<=n;i++)v[i]=tmp[i]=read(); sort(tmp+1,tmp+n+1);tot=unique(tmp+1,tmp+n+1)-tmp-1; for(int i=1;i<=n;i++)v[i]=lower_bound(tmp+1,tmp+tot+1,v[i])-tmp; for(int i=1;i<n;i++)x=read(),y=read(),insert(x,y); deep[1]=1;dfs(1); for(int i=1;i<=n;i++) { temp=num[i]; update(root[i],root[id[fa[temp][0]]],1,tot,v[temp]); } for(int i=1;i<=m;i++) { x=read();y=read();rk=read();x^=lastans; lastans=query(x,y,rk);printf("%d",lastans); if(i!=m)printf("\n"); } return 0; }View Code
相关文章推荐
- BZOJ 2588: Spoj 10628. Count on a tree | 树上主席树
- BZOJ 2588 Spoj 10628. Count on a tree
- BZOJ 2588 Spoj 10628. Count on a tree 主席树
- [BZOJ2588][SPOJ10628]Count on a tree
- bzoj2588 Spoj 10628. Count on a tree【主席树+lca】
- BZOJ 2588: Spoj 10628. Count on a tree
- 【bzoj2588】Spoj 10628. Count on a tree LCA+主席树
- bzoj 2588 Spoj 10628. Count on a tree
- bzoj2588: Spoj 10628. Count on a tree 主席树+dfs序
- [主席树] BZOJ2588: Spoj 10628. Count on a tree
- BZOJ2588 Spoj 10628. Count on a tree
- 【BZOJ 2588】 Spoj 10628. Count on a tree|树上K大|树链剖分|主席树
- BZOJ2588 Spoj 10628. Count on a tree
- bzoj 2588: Spoj 10628. Count on a tree LCA+主席树
- [bzoj 2588] Spoj 10628. Count on a tree:函数式线段树
- [BZOJ]2588 Spoj 10628. Count on a tree 树链第k大 PE的进来看看
- [bzoj2588][Spoj 10628] Count on a tree
- bzoj2588 Spoj 10628. Count on a tree
- BZOJ 2588 Spoj 10628 Count on a tree
- 【BZOJ2588】Spoj 10628. Count on a tree 主席树+LCA