【树上主席树】BZOJ2588-Count on a tree
【题目大意】
给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。
【思路】
这道题迷之好写,因为思路条理太清晰了!
我们每个点就是一棵线段树,维护它到根的每个数字的个数,但是这样会MLE所以自然而然地用主席树来维护。
u->v路径上每种的个数就等于sum[u]-sum[lca(u,v)]+sum[v]-sum[fa[lca(u,v)]]。
写起来特别爽。
然而我RE了一个上午。接着突然发现题意“(u,v)表示u到v有一条边)它居然是无向的??天真地以为有向u->v,调出了一开始的程序,默默地改掉,默默地AC...
还我两小时的人生!!!!
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 #define lson l,m 7 #define rson m+1,r 8 using namespace std; 9 const int MAXN=100000+500; 10 const int DEG=20; 11 int w[MAXN]; 12 vector<int> E[MAXN]; 13 int d,hash[MAXN]; 14 int T[MAXN],tot,sum[MAXN<<5],L[MAXN<<5],R[MAXN<<5]; 15 int anc[MAXN][DEG],dep[MAXN]; 16 int n,m; 17 18 /*Chairman Tree*/ 19 int build(int l,int r) 20 { 21 int rt=++tot; 22 sum[rt]=0; 23 if (l!=r) 24 { 25 int m=(l+r)>>1; 26 L[rt]=build(lson); 27 R[rt]=build(rson); 28 } 29 return rt; 30 } 31 32 int update(int pre,int l,int r,int x) 33 { 34 int rt=++tot; 35 L[rt]=L[pre],R[rt]=R[pre]; 36 sum[rt]=sum[pre]+1; 37 if (l!=r) 38 { 39 int m=(l+r)>>1; 40 if (x<=m) L[rt]=update(L[pre],lson,x); 41 else R[rt]=update(R[pre],rson,x); 42 } 43 return rt; 44 } 45 46 int query(int u,int v,int lca,int lcafa,int l,int r,int k) 47 { 48 if (l==r) return l; 49 int num=(sum[L[u]]-sum[L[lca]]+sum[L[v]]-sum[L[lcafa]]); 50 int m=(l+r)>>1; 51 if (num>=k) return query(L[u],L[v],L[lca],L[lcafa],lson,k); 52 else return query(R[u],R[v],R[lca],R[lcafa],rson,k-num); 53 } 54 55 /*LCA*/ 56 void getanc() 57 { 58 for (int i=1;i<DEG;i++) 59 for (int j=1;j<=n;j++) 60 anc[j][i]=anc[anc[j][i-1]][i-1]; 61 } 62 63 int swim(int x,int H) 64 { 65 for (int i=0;H>0;i++) 66 { 67 if (H&1) x=anc[x][i]; 68 H>>=1; 69 } 70 return x; 71 } 72 73 int LCA(int u,int v) 74 { 75 if (dep[u]<dep[v]) swap(u,v); 76 u=swim(u,dep[u]-dep[v]); 77 if (u==v) return u; 78 for (int i=DEG-1;i>=0;i--) 79 { 80 if (anc[u][i]!=anc[v][i]) 81 { 82 u=anc[u][i]; 83 v=anc[v][i]; 84 } 85 } 86 return anc[u][0]; 87 } 88 89 /*main*/ 90 void dfs(int u,int pa,int depth) 91 { 92 anc[u][0]=pa; 93 dep[u]=depth; 94 int x=lower_bound(hash+1,hash+d+1,w[u])-hash; 95 T[u]=update(T[pa],1,d,x); 96 for (int i=0;i<E[u].size();i++) 97 if (E[u][i]!=pa) dfs(E[u][i],u,depth+1); 98 } 99 100 void init() 101 { 102 scanf("%d%d",&n,&m); 103 for (int i=1;i<=n;i++) scanf("%d",&w[i]),hash[i]=w[i]; 104 sort(hash+1,hash+n+1); 105 d=unique(hash+1,hash+n+1)-(hash+1); 106 107 for (int i=1;i<n;i++) 108 { 109 int u,v; 110 scanf("%d%d",&u,&v); 111 E[u].push_back(v); 112 E[v].push_back(u); 113 } 114 115 116 tot=0; 117 T[1]=build(1,d);//对于根先建立主席树 118 } 119 120 void solve() 121 { 122 getanc(); 123 int preans=0; 124 for (int i=0;i<m;i++) 125 { 126 int u,v,k; 127 scanf("%d%d%d",&u,&v,&k); 128 u=u^preans; 129 int lca=LCA(u,v); 130 int ans=query(T[u],T[v],T[lca],T[anc[lca][0]],1,d,k); 131 printf("%d",hash[ans]); 132 if (i!=m-1) printf("\n"); 133 preans=hash[ans]; 134 } 135 } 136 137 int main() 138 { 139 init(); 140 dfs(1,0,1); 141 solve(); 142 return 0; 143 }