《P2633 Count on a tree》
树上查询某一路径上的第k大。
首先,我们只需要处理出路径上的权值线段树即可。
我们建立根到u的前缀和主席树。
那么对于查询u,v。和树上距离的类似。
sum[u] + sum[v] - sum[lca(u,v]] - sum[fa[lca(u,v]]]。
因为这里的话,lca的值也需要算入。所以第二次减去lca的fa的值。这样就不会少去lca点的值了。
那么就可以查询了。
这里因为一个小错误一直RE,调了很久。。。。。
应该先让u ^= ans,再去求lca。
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<string,int> pii; const int N = 1e5+5; const int M = 2e5+5; const LL Mod = 199999; #define rg register #define pi acos(-1) #define INF 1e9 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline 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<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } void print(int x){ if(x < 0){x = -x;putchar('-');} if(x > 9) print(x/10); putchar(x%10+'0'); } } using namespace FASTIO; void FRE(){/*freopen("data1.in","r",stdin); freopen("data1.out","w",stdout);*/} int n,m,a[N],b[N],mp[N],rt[N],dep[N],f[N][20],lg[N],top = 0,len; struct Node{int L,r;LL sum;}node[N*50]; vector<int> G[N]; void init() { for(rg int i = 1;i < N;++i) lg[i] = lg[i-1]+((1<<lg[i-1]) == i); } int build(int L,int r) { int idx = ++top; node[idx].sum = 0; if(L == r) return idx; int mid = (L+r)>>1; node[idx].L = build(L,mid); node[idx].r = build(mid+1,r); return idx; } void Pushup(int idx) { node[idx].sum = node[node[idx].L].sum + node[node[idx].r].sum; } int update(int x,int L,int r,int pos) { int idx = ++top; node[idx] = node[x]; if(L == r){node[idx].sum++;return idx;} int mid = (L+r)>>1; if(mid >= pos) node[idx].L = update(node[x].L,L,mid,pos); else node[idx].r = update(node[x].r,mid+1,r,pos); Pushup(idx); return idx; } void dfs(int u,int fa) { rt[u] = update(rt[fa],1,len,b[u]); dep[u] = dep[fa]+1,f[u][0] = fa; for(rg int i = 1;i <= lg[dep[u]];++i) f[u][i] = f[f[u][i-1]][i-1]; for(auto v : G[u]) if(v != fa) dfs(v,u); } int LCA(int x,int y) { if(dep[x] < dep[y]) swap(x,y); while(dep[x] > dep[y]) x = f[x][lg[dep[x]-dep[y]]-1]; if(x == y) return x; for(rg int i = lg[dep[x]]-1;i >= 0;--i) { if(f[x][i] != f[y][i]) x = f[x][i],y = f[y][i]; } return f[x][0]; } int query_kth(int ll,int rr,int fa,int ffa,int L,int r,int k) { if(L == r) return mp[L]; int mid = (L+r)>>1; int lsum = node[node[ll].L].sum+node[node[rr].L].sum-node[node[fa].L].sum-node[node[ffa].L].sum; if(lsum >= k) return query_kth(node[ll].L,node[rr].L,node[fa].L,node[ffa].L,L,mid,k); else return query_kth(node[ll].r,node[rr].r,node[fa].r,node[ffa].r,mid+1,r,k-lsum); } int main() { init(); n = read(),m = read(); for(rg int i = 1;i <= n;++i) a[i] = read(),b[i] = a[i]; sort(a+1,a+n+1); len = unique(a+1,a+n+1)-a-1; for(rg int i = 1;i <= n;++i) { int pos = lower_bound(a+1,a+len+1,b[i])-a; mp[pos] = b[i],b[i] = pos; } for(rg int i = 1;i < n;++i) { int x,y;x = read(),y = read(); G[x].push_back(y); G[y].push_back(x); } rt[0] = build(1,len); dfs(1,0); int ans = 0; while(m--) { int u,v,k;u = read(),v = read(),k = read(); u ^= ans; int lca = LCA(u,v); ans = query_kth(rt[u],rt[v],rt[lca],rt[f[lca][0]],1,len,k); printf("%d\n",ans); } system("pause"); } /* 8 20 105 2 9 3 8 5 7 7 1 2 1 3 1 4 3 5 3 6 3 7 4 8 */