[luogu P2633] 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
暴力自重。。。
来源:bzoj2588 Spoj10628.
本题数据为洛谷自造数据,使用CYaRon耗时5分钟完成数据制作。
主席树的变形,离散后,对于每个点u构造一棵新的主席树都建立在以fa[u][0]构造的主席树的基础之上。
其中,要按照dfs序来造,才能保证正确性。(用bfs序当然也可以咯)
然后询问两个点(x,y)时,根据主席树可加减的性质,只要在tree[x]+tree[y]-tree[lca(x,y)]-tree[fa[lca(x,y)]]这棵树上查询就可以了。
注意强制在线。
code:
View Code1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <tr1/unordered_map> 5 #define ms(a,x) memset(a,x,sizeof a) 6 using namespace std; 7 void OJ() { 8 #ifndef ONLINE_JUDGE 9 freopen("in.txt","r",stdin); 10 freopen("out.txt","w",stdout); 11 #endif 12 } 13 14 namespace fastIO { 15 #define gec(c) getchar(c) 16 #define puc(c) putchar(c) 17 char ch; 18 inline int read() { 19 int x=0,f=1; ch=getchar(); 20 while (ch<'0'||ch>'9') { 21 if (ch=='-') f=-f; 22 ch=gec(); 23 } 24 while (ch>='0'&&ch<='9') { 25 x=(x<<3)+(x<<1)+ch-'0'; 26 ch=getchar(); 27 } 28 return x*f; 29 } 30 int ttt,nnn[20]; 31 template <class T> inline void write(T x) { 32 if (x==0) { 33 puc('0'); return; 34 } 35 if (x<0) x=-x,puc('-'); 36 for (ttt=0; x; x/=10) nnn[++ttt]=x%10; 37 for (; ttt; --ttt) puc(nnn[ttt]+48); 38 } 39 inline void newline() { 40 puc('\n'); 41 } 42 } using namespace fastIO; 43 44 const int N=100005; 45 int n,m,cnt,b[N]; 46 int tot,lnk[N],nxt[N<<1],son[N<<1]; 47 int dep[N],fa[N][20],dfn[N],rel[N],clo; 48 tr1::unordered_map <int,int> ref; 49 struct data { 50 int x,i; 51 } a[N]; 52 inline bool cmp_x (const data &u,const data &v) { 53 return u.x<v.x; 54 } 55 inline bool cmp_i (const data &u,const data &v) { 56 return u.i<v.i; 57 } 58 struct node { 59 node* l,* r; int v; 60 node () { 61 l=r=0,v=0; 62 } 63 } *r[N]; 64 #define M ((l)+(r)>>1) 65 inline void setup (node* &c,int l,int r) { 66 c=new node(); 67 if (l==r) return; 68 setup(c->l,l,M),setup(c->r,M+1,r); 69 } 70 inline void insert (node* &c,int l,int r,int x,node* his) { 71 c=new node(); 72 c->l=his->l,c->r=his->r,c->v=his->v+1; 73 if (l==r) return; 74 if (x<=M) insert(c->l,l,M,x,his->l); 75 else insert(c->r,M+1,r,x,his->r); 76 } 77 inline int reply (node* x,node* y,node* z,node* o,int l,int r,int k,int v=0) { 78 if (l==r) return b[l]; 79 v+=x->l->v,v+=y->l->v; 80 v-=z->l->v,v-=o->l->v; 81 if (k<=v) return reply(x->l,y->l,z->l,o->l,l,M,k); 82 else return reply(x->r,y->r,z->r,o->r,M+1,r,k-v); 83 } 84 void add (int x,int y) { 85 nxt[++tot]=lnk[x],lnk[x]=tot,son[tot]=y; 86 } 87 void dfs (int x,int p) { 88 dep[x]=dep[p]+1,fa[x][0]=p,rel[dfn[x]=++clo]=x; 89 for (int j=1; j<=18; ++j) fa[x][j]=fa[fa[x][j-1]][j-1]; 90 for (int j=lnk[x]; j; j=nxt[j]) { 91 if (son[j]!=p) dfs(son[j],x); 92 } 93 } 94 int lca (int x,int y) { 95 if (dep[x]<dep[y]) swap(x,y); 96 if (y==1) return 1; 97 int dif=dep[x]-dep[y]; 98 for (int j=18; ~j; --j) 99 if (dif&(1<<j)) x=fa[x][j]; 100 if (x==y) return x; 101 for (int j=18; ~j; --j) 102 if (fa[x][j]!=fa[y][j]) x=fa[x][j],y=fa[y][j]; 103 return fa[x][0]; 104 } 105 int main() { 106 OJ(); int x,y,z,o,k,lastans=0; 107 n=read(),m=read(); 108 for (int i=1; i<=n; ++i) a[i].x=read(); 109 for (int i=1; i<n; ++i) { 110 x=read(),y=read(); 111 add(x,y),add(y,x); 112 } 113 dep[0]=0,dfn[0]=0,dfs(1,0); 114 for (int i=1; i<=n; ++i) a[i].i=dfn[i]; 115 sort(a+1,a+1+n,cmp_x); 116 b[cnt=ref[a[1].x]=1]=a[1].x; 117 for (int i=2; i<=n; i++) 118 if (a[i].x!=a[i-1].x) b[ref[a[i].x]=++cnt]=a[i].x; 119 sort(a+1,a+1+n,cmp_i); 120 setup(r[0],1,cnt); 121 for (int i=1; i<=n; ++i) insert(r[i],1,cnt,ref[a[i].x],r[dfn[fa[rel[i]][0]]]); 122 for (int i=1; i<=m; ++i) { 123 x=read(),x^=lastans,y=read(),z=lca(x,y),o=fa[z][0],k=read(); 124 x=dfn[x],y=dfn[y],z=dfn[z],o=dfn[o]; 125 write(lastans=reply(r[x],r[y],r[z],r[o],1,cnt,k)); 126 if (i^m) newline(); 127 } 128 return 0; 129 }