【BZOJ2588】Count On a Tree(主席树)

时间:2023-02-12 21:32:54

【BZOJ2588】Count On a Tree(主席树)

题面

题目描述

给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。

输入格式:

第一行两个整数N,M。

第二行有N个整数,其中第i个整数表示点i的权值。

后面N-1行每行两个整数(x,y),表示点x到点y有一条边。

最后M行每行两个整数(u,v,k),表示一组询问。

输出格式:

M行,表示每个询问的答案。

输入输出样例

输入样例#1:

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

输出样例#1:

2

8

9

105

7

说明

HINT:

N,M<=100000

题解

链上的第k大->主席树

这题怎么搞得话

对于每一个节点建立一个线段树(显然开不下)

每个节点继承父节点再加上自己

主席树搞一下

查询的时候,跳\(u,v,lca,father(lca)\)四棵线段树就行了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define MAX 110000
#define lson (t[now].ls)
#define rson (t[now].rs)
inline int read()
{
int x=0,t=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
struct Line
{
int v,next;
}e[MAX<<1];
int h[MAX],cnt=1;
int n,m,sum;
int a[MAX],S[MAX],tot,z[MAX];
int rt[MAX];
struct Node
{
int ls,rs;
int v;
}t[MAX<<5];
inline void Add(int u,int v)
{
e[cnt]=(Line){v,h[u]};
h[u]=cnt++;
}
void Build(int &now,int l,int r)
{
now=++tot;
if(l==r)return;
int mid=(l+r)>>1;
Build(lson,l,mid);
Build(rson,mid+1,r);
}
void Update(int &now,int ff,int l,int r,int pos)
{
now=++tot;
t[now]=t[ff];
t[now].v++;
if(l==r)return;
int mid=(l+r)>>1;
if(pos<=mid)Update(lson,t[ff].ls,l,mid,pos);
else Update(rson,t[ff].rs,mid+1,r,pos);
}
int Query(int r1,int r2,int r3,int r4,int l,int r,int k)
{
if(l==r)return l;
int tmp=t[t[r1].ls].v+t[t[r2].ls].v-t[t[r3].ls].v-t[t[r4].ls].v;
int mid=(l+r)>>1;
if(k<=tmp)return Query(t[r1].ls,t[r2].ls,t[r3].ls,t[r4].ls,l,mid,k);
else return Query(t[r1].rs,t[r2].rs,t[r3].rs,t[r4].rs,mid+1,r,k-tmp);
}
int hson[MAX],fa[MAX],size[MAX],dep[MAX],top[MAX];
void dfs1(int u,int ff)
{
fa[u]=ff;size[u]=1;dep[u]=dep[ff]+1;
Update(rt[u],rt[ff],1,sum,a[u]);
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;
if(v==ff)continue;
dfs1(v,u);
size[u]+=size[v];
if(size[v]>size[hson[u]])hson[u]=v;
}
}
void dfs2(int u,int tp)
{
top[u]=tp;
if(hson[u])dfs2(hson[u],tp);
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;
if(v==fa[u]||v==hson[u])continue;
dfs2(v,v);
}
}
int LCA(int u,int v)
{
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])swap(u,v);
u=fa[top[u]];
}
return dep[u]<dep[v]?u:v;
}
int main()
{
n=sum=read();m=read();
for(int i=1;i<=n;++i)S[i]=a[i]=z[i]=read();
sort(&S[1],&S[n+1]);
sum=unique(&S[1],&S[sum+1])-S-1;
for(int i=1;i<=n;++i)a[i]=(lower_bound(&S[1],&S[sum+1],a[i])-S);
for(int i=1;i<n;++i)
{
int x=read(),y=read();
Add(x,y);Add(y,x);
}
Build(rt[0],1,sum);
dfs1(1,0);dfs2(1,1);
int lans=0;
while(m--)
{
int u=read()^lans,v=read(),k=read();
int lca=LCA(u,v);
printf("%d\n",lans=S[Query(rt[u],rt[v],rt[lca],rt[fa[lca]],1,sum,k)]);
}
return 0;
}