您的位置:首页 > 其它

BZOJ[2588]Count on a tree 主席树

2018-03-12 10:18 393 查看
传送门ber~

每个点到根这一段区间建一棵主席树

那么两点x,yx,y之间的信息可以表示为sumx+sumy−sumLCA(x,y)−sumfa[LCA(x,y)]sumx+sumy−sumLCA(x,y)−sumfa[LCA(x,y)]

这样就兹瓷第kk大了

代码如下:

#include<algorithm>
#include<ctype.h>
#include<cstdio>
#define N 100050
using namespace std;
inline int read(){
int x=0,f=1;char c;
do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));
do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));
return x*f;
}
int n,m,x,y,k,t,top,tot,las;
int fir
,a
,b
,f
[21],dep
;
struct Edge{
int to,nex;
Edge(int _=0,int __=0):to(_),nex(__){}
}nex[N<<1];
struct Node{
Node *ls,*rs;
int sum;
Node();
inline void maintain(){
sum=ls->sum+rs->sum;
return;
}
}*root
,*null;
Node::Node():ls(null),rs(null),sum(0){}
inline void init(){
null=new Node;
null->ls=null->rs=null;
null->sum=0;
root[0]=null;
return;
}
inline void add(int x,int y){
nex[++top]=Edge(y,fir[x]);
fir[x]=top;
}
void Add(int L,int R,int x,Node *&k,Node *pre){
if(k==null) k=new Node;
if(L==R){
k->sum=pre->sum+1;
return;
}
int mid=L+R>>1;
if(x<=mid){
Add(L,mid,x,k->ls,pre->ls);
k->rs=pre->rs;
}
else{
Add(mid+1,R,x,k->rs,pre->rs);
k->ls=pre->ls;
}
k->maintain();
return;
}
void dfs(int x,int fa,int Dep){
f[x][0]=fa;dep[x]=Dep;
Add(1,tot,a[x],root[x]=null,root[fa]);
for(int i=fir[x];i;i=nex[i].nex){
if(nex[i].to==fa) continue;
dfs(nex[i].to,x,Dep+1);
}
}
inline int LCA(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int i=19;~i;i--)
if(dep[f[x][i]]>=dep[y])
x=f[x][i];
if(x==y) return x;
for(int i=19;~i;i--)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
int Query(int L,int R,int k,Node *x,Node *y,Node *lca,Node *flca){
if(L==R) return L;
int sum=x->ls->sum+y->ls->sum-lca->ls->sum-flca->ls->sum;
int mid=L+R>>1;
if(sum>=k) return Query(L,mid,k,x->ls,y->ls,lca->ls,flca->ls);
else return Query(mid+1,R,k-sum,x->rs,y->rs,lca->rs,flca->rs);
}
int main(){
init();
n=read();m=read();
for(int i=1;i<=n;i++)
b[i]=a[i]=read();
sort(b+1,b+n+1);
tot=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++)
a[i]=lower_bound(b+1,b+tot+1,a[i])-b;
for(int i=1;i<n;i++){
x=read();y=read();
add(x,y);add(y,x);
}
dfs(1,0,1);
for(int j=1;j<=19;j++)
for(int i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1];
for(int i=1;i<=m;i++){
x=read()^las;y=read();k=read();
t=LCA(x,y);
las=b[Query(1,tot,k,root[x],root[y],root[t],root[f[t][0]])];
printf(i==m?"%d":"%d\n",las);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: