bzoj 2588 : Spoj 10628. Count on a tree

时间:2023-03-09 20:14:22
bzoj 2588 : 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

HINT:
N,M<=100000
暴力自重。。。
思路:
强制在线,lca + 主席树
实现代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m = (l + r) >> 1
const int M = 2e5 + ;
int p[M][],dep[M],head[M],sum[M*],ls[M*],rs[M*],root[M*];
int cnt1,n,idx,cnt,f[M]; struct node {
int to,next;
}e[M]; void add(int u,int v){
e[++cnt1].to=v;e[cnt1].next=head[u];head[u]=cnt1;
e[++cnt1].to=u;e[cnt1].next=head[v];head[v]=cnt1;
} int lca(int a,int b){
if(dep[a] > dep[b]) swap(a,b);
int h = dep[b] - dep[a];
for(int i = ;(<<i)<=h;i++){
if((<<i)&h) b = p[b][i];
} if(a!=b){
for(int i = ;i >= ;i --){
if(p[a][i]!=p[b][i]){
a = p[a][i]; b = p[b][i];
}
}
a = p[a][];
}
return a;
} void build(int l,int r,int &rt){
rt = ++idx;
sum[rt] = ;
if(l == r) return;
mid;
build(l,m,ls[rt]);
build(m+,r,rs[rt]);
} void update(int p,int l,int r,int old,int &rt){
rt = ++idx;
ls[rt] = ls[old]; rs[rt] = rs[old]; sum[rt] = sum[old] + ;
if(l == r) return ;
mid;
if(p <= m) update(p,l,m,ls[old],ls[rt]);
else update(p,m+,r,rs[old],rs[rt]);
} int query(int a,int b,int lc,int cl,int l,int r,int k){
if(l == r) return l;
mid;
int cnt = sum[ls[a]] + sum[ls[b]] - sum[ls[lc]] - sum[ls[cl]];
if(k <= cnt)
return query(ls[a],ls[b],ls[lc],ls[cl],l,m,k);
else
return query(rs[a],rs[b],rs[lc],rs[cl],m+,r,k-cnt);
}
int a[M],b[M]; void dfs(int u,int fa){
f[u] = fa;
update(a[u],,cnt,root[fa],root[u]);
for(int i = head[u];i;i = e[i].next){
int v = e[i].to;
if(v == fa) continue;
p[v][] = u;
dep[v] = dep[u] + ;
dfs(v,u);
}
} void init()
{
cnt1 = ; idx = ;
memset(head,,sizeof(head));
memset(dep,,sizeof(dep));
memset(p,,sizeof(p));
memset(f,,sizeof(f));
dep[] = ;
} int main()
{
int m;
while(scanf("%d%d",&n,&m)!=EOF){
init();
for(int i = ; i <= n;i ++){
scanf("%d",&a[i]);
b[i] = a[i];
}
int l,r,c;
sort(b+,b+n+);
cnt = unique(b+,b++n)-b-;
for(int i = ;i <= n;i ++)
a[i] = lower_bound(b+,b+cnt+,a[i]) - b;
for(int i = ;i <= n-;i ++){
scanf("%d%d",&l,&r);
add(l,r);
}
build(,cnt,root[]);
dfs(,);
for(int j = ;(<<j)<=n;j++)
for(int i = ;i <= n;i++)
p[i][j] = p[p[i][j-]][j-];
int num = ;
for(int i = ;i <= m;i ++){
scanf("%d%d%d",&l,&r,&c);
l = l^num;
int lc = lca(l,r);
int id = query(root[l],root[r],root[lc],root[f[lc]],,cnt,c);
num = b[id];
printf("%d\n",b[id]);
}
}
return ;
}