bzoj2588 Spoj 10628. Count on a tree

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
暴力自重。。。

正解:树上主席树

利用树上前缀和的思想来进行主席树的操作,用dfs序存储每个结点的信息,然后就是道主席树版子题了。。

 

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <cstdio>
 7 #include <vector>
 8 #include <cmath>
 9 #include <queue>
10 #include <stack>
11 #include <map>
12 #include <set>
13 #define inf 1<<30
14 #define il inline
15 #define RG register
16 #define ll long long
17 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
18 
19 using namespace std;
20 
21 struct edge{ int nt,to; }g[200010];
22 
23 int head[100010],size[100010],dep[100010],dfn[100010],top[100010],fa[100010],son[100010],a[100010],num[100010],hashh[100010],root[100010],sum[5000010],ls[5000010],rs[5000010],m,n,N,sz,tot,cnt,pre;
24 
25 il int gi(){
26     RG int x=0,q=0; RG char ch=getchar();
27     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); if (ch=='-') q=1,ch=getchar();
28     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q ? -x : x;
29 }
30 
31 il void ins(RG int from,RG int to){ g[++N]=(edge){head[from],to},head[from]=N; return; }
32 
33 il void insert(RG int l,RG int r,RG int x,RG int &y,RG int v){
34     y=++sz,sum[y]=sum[x]+1; if (l==r) return; ls[y]=ls[x],rs[y]=rs[x]; RG int mid=(l+r)>>1;
35     if (v<=mid) insert(l,mid,ls[x],ls[y],v); else insert(mid+1,r,rs[x],rs[y],v); return;
36 }
37 
38 il void dfs1(RG int x,RG int p){
39     dfn[x]=++cnt,dep[x]=dep[p]+1,fa[x]=p,size[x]=1; RG int v,mx=0;
40     for (RG int i=head[x];i;i=g[i].nt){
41     v=g[i].to; if (v==p) continue; dfs1(v,x);
42     size[x]+=size[v]; if (size[mx]<size[v]) mx=v;
43     }
44     son[x]=mx; return;
45 }
46 
47 il void dfs2(RG int x,RG int p,RG int anc){
48     insert(1,tot,root[dfn[p]],root[dfn[x]],lower_bound(hashh+1,hashh+tot+1,a[x])-hashh);
49     top[x]=anc; if (son[x]) dfs2(son[x],x,anc); RG int v;
50     for (RG int i=head[x];i;i=g[i].nt){
51     v=g[i].to; if (v==p || v==son[x]) continue; dfs2(v,x,v);
52     }
53     return;
54 }
55 
56 il int lca(RG int u,RG int v){
57     RG int t; while (top[u]!=top[v]){ if (dep[top[u]]<dep[top[v]]) t=u,u=v,v=t; u=fa[top[u]]; }
58     if (dep[u]<dep[v]) return u; else return v;
59 }
60 
61 il int query(RG int a,RG int b,RG int k){
62     RG int c=lca(a,b),d=fa[c],L=1,R=tot,mid,tmp;
63     a=root[dfn[a]],b=root[dfn[b]],c=root[dfn[c]],d=root[dfn[d]];
64     while (L<R){
65     mid=(L+R)>>1,tmp=sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]];
66     if (k<=tmp) R=mid,a=ls[a],b=ls[b],c=ls[c],d=ls[d];
67     else L=mid+1,k-=tmp,a=rs[a],b=rs[b],c=rs[c],d=rs[d];
68     }
69     return hashh[L];
70 }
71 
72 il void work(){
73     n=gi(),m=gi(); for (RG int i=1;i<=n;++i) num[i]=a[i]=gi();
74     for (RG int i=1;i<n;++i){ RG int u=gi(),v=gi(); ins(u,v),ins(v,u); } sort(num+1,num+n+1);
75     hashh[++tot]=num[1]; for (RG int i=2;i<=n;++i) if (num[i]!=num[i-1]) hashh[++tot]=num[i];
76     dfs1(1,0),dfs2(1,0,1);
77     for (RG int i=1;i<=m;++i){
78     RG int u=gi(),v=gi(),k=gi(); pre=query(u^pre,v,k);
79     printf("%d",pre); if (i!=m) printf("\n");
80     }
81     return;
82 }
83 
84 int main(){
85     File("chairtree");
86     work();
87     return 0;
88 }

 

posted @ 2017-01-19 20:19  wfj_2048  阅读(129)  评论(0编辑  收藏  举报