[bzoj2588][ Count on a tree]
阿新 • • 發佈:2018-12-11
題目連結
思路
查詢區間第k小,考慮主席樹。因為是從u到v的簡單路徑上,考慮將路徑分為從u到lca和從lca到v兩部分。所以對於每個點都維護出從根節點到當前節點中的點。查詢的時候只要用ans[u] + ans[v] - ans[lca] - ans[fa[lca]]就行了。也就是在主席樹的查詢程式碼上略加修改。
程式碼
/* * @Author: wxyww * @Date: 2018-12-11 17:19:03 * @Last Modified time: 2018-12-11 18:05:14 */ #include<cstdio> #include<iostream> #include<cstdlib> #include<map> #include<cmath> #include<ctime> #include<algorithm> #include<bitset> #include<vector> using namespace std; typedef long long ll; const int N = 100000 + 100,logN = 19; vector<int>e[N]; map<int,int>ma; ll read() { ll 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; } int js,n,tot; int w[N],tree[N * 30],ls[N * 30],root[N],rs[N * 30],dy[N]; int lca[N][logN + 5],dep[N]; void get_lca(int u,int father) { for(int i = 1;i <= logN;++i) lca[u][i] = lca[lca[u][i - 1]][i - 1]; int k = e[u].size(); for(int i = 0;i < k;++i) { int v = e[u][i]; if(v == father) continue; lca[v][0] = u; dep[v] = dep[u] + 1; get_lca(v,u); } } int LCA(int x,int y) { if(dep[x] < dep[y]) swap(x,y); for(int i = logN;i >= 0;--i) if(dep[lca[x][i]] >= dep[y]) x = lca[x][i]; if(x == y) return x; for(int i = logN;i >= 0;--i) if(lca[x][i] != lca[y][i]) x = lca[x][i],y = lca[y][i]; return lca[x][0]; } void update(int &rt,int lst,int l,int r,int pos) { rt = ++tot; ls[rt] = ls[lst];rs[rt] = rs[lst]; tree[rt] = tree[lst] + 1; if(l == r) return; int mid = (l + r) >> 1; if(pos <= mid) update(ls[rt],ls[lst],l,mid,pos); else update(rs[rt],rs[lst],mid + 1,r,pos); } int query(int L,int R,int Lca,int falca,int k,int l,int r) { int z = tree[ls[L]] + tree[ls[R]] - tree[ls[Lca]] - tree[ls[falca]];//與普通主席樹不同的地方 if(l == r) return l; int mid = (l + r) >> 1; if(k <= z) return query(ls[L],ls[R],ls[Lca],ls[falca],k,l,mid); else return query(rs[L],rs[R],rs[Lca],rs[falca],k - z,mid + 1,r); } void dfs(int u,int father) { int k = e[u].size(); update(root[u],root[father],1,js,w[u]); for(int i = 0;i < k;++i) { int v = e[u][i]; if(v == father) continue; dfs(v,u); } } int main() { n = read();int m = read(); for(int i = 1;i <= n;++i) ls[i] = w[i] = read(); sort(ls + 1,ls + n + 1); ma[ls[1]] = ++js; dy[js] = ls[1]; for(int i = 2; i <= n;++i) if(ls[i] != ls[i - 1]) ma[ls[i]] = ++js,dy[js] = ls[i]; for(int i = 1;i <= n;++i) w[i] = ma[w[i]]; for(int i = 1;i < n;++i) { int u = read(),v = read(); e[u].push_back(v);e[v].push_back(u); } dfs(1,0); dep[1] = 1; get_lca(1,0); int LST = 0; while(m--) { int l = read() ^ LST,r = read(),k = read(); int z = LCA(l,r); // printf("%d %d %d\n",l,r,z); LST = dy[query(root[l],root[r],root[z],root[lca[z][0]],k,1,js)]; printf("%d\n",LST); } return 0; }