题解: 树上主席树转移 建权值线段树即可(
#include <bits/stdc++.h> const int MAXN=1e5+10; using namespace std; typedef struct node{ int l,r,sum; }node; node d[MAXN*21];int rt[MAXN],cnt,f[MAXN][21],a[MAXN]; vector<int>vec[MAXN]; int n,m; void update(int &x,int y,int l,int r,int t){ x=++cnt;d[x]=d[y];d[x].sum++; if(l==r)return ; int mid=(l+r)>>1; if(t<=mid)update(d[x].l,d[y].l,l,mid,t); else update(d[x].r,d[y].r,mid+1,r,t); } int querty(int x,int y,int x1,int y1,int l,int r,int k){ if(l==r)return l; int mid=(l+r)>>1; int t1=d[d[x1].l].sum+d[d[y1].l].sum-d[d[x].l].sum-d[d[y].l].sum; if(t1>=k)return querty(d[x].l,d[y].l,d[x1].l,d[y1].l,l,mid,k); else return querty(d[x].r,d[y].r,d[x1].r,d[y1].r,mid+1,r,k-t1); } int dep[MAXN]; void dfs(int v,int pre,int deep){ f[v][0]=pre;dep[v]=deep+1; update(rt[v],rt[pre],1,n,a[v]); for(int i=0;i<vec[v].size();i++){ if(vec[v][i]!=pre)dfs(vec[v][i],v,deep+1); } } void dfs1(int v){ for(int i=1;i<=20;i++)f[v][i]=f[f[v][i-1]][i-1]; for(int i=0;i<vec[v].size();i++)if(vec[v][i]!=f[v][0])dfs1(vec[v][i]); } int Lca(int u,int v){ if(dep[u]<dep[v])swap(u,v); int tmp=dep[u]-dep[v]; for(int i=0;i<=20;i++)if((tmp&(1<<i)))u=f[u][i]; if(u==v)return u; for(int i=20;i>=0;i--){ if(f[u][i]!=f[v][i]){ u=f[u][i];v=f[v][i]; } } return f[u][0]; } vector<int>v1; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i]),v1.push_back(a[i]); sort(v1.begin(),v1.end()); int sz=unique(v1.begin(),v1.end())-v1.begin(); for(int i=1;i<=n;i++)a[i]=lower_bound(v1.begin(),v1.begin()+sz,a[i])-v1.begin()+1; int u,v,res=0,k; for(int i=1;i<n;i++)scanf("%d%d",&u,&v),vec[u].push_back(v),vec[v].push_back(u); dfs(1,0,0);dfs1(1); for(int i=1;i<=m;i++){ scanf("%d%d%d",&u,&v,&k); u^=res;int lca=Lca(u,v); res=v1[querty(rt[lca],rt[f[lca][0]],rt[u],rt[v],1,n,k)-1]; printf("%d ",res); } return 0; }
2588: Spoj 10628. Count on a tree
Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 8749 Solved: 2224
[Submit][Status][Discuss]
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
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
8
9
105
7
HINT
HINT:
N,M<=100000
暴力自重。。。