主席树练习2——P2633 Count on a tree

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Love_mona/article/details/79802679

蒟蒻的垂死挣扎


接下来做经典题。

这个是树上路径第K大,开始十分懵逼,感觉是树剖,但是仔细想想又不对,再仔细想想就发现自己是个傻子,这里直接对父节点新开树就可以了,即状态由父节点转移,相当于点到根的前缀和,自己yy一下就可以想出查询时候的线段树减法怎么做,然后就可以轻松ac啦。

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#define RG register
#define N 100100
#define ll long long
#define ld long double
using namespace std;

inline ll read(){
  RG ll x=0,o=1; RG char ch=getchar();
  while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
  if(ch=='-') o=-1,ch=getchar();
  while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
  return x*o;
}

int top,len,n,m,a[N],b[N],yyb[N],tot,root[N],f[N][20],dep[N],first[N];
struct mona { int le,ri; int w; } tr[N*80];
struct joker{ int nxt,en;       } s[N<<1];

inline void Build(RG int l,RG int r,RG int &x,RG int y,RG int w){
    tr[++tot]=tr[y],++tr[tot].w,x=tot;
    if(l==r) return ;
    RG int mid=(l+r)>>1;
    if(w<=mid) Build(l,mid,tr[x].le,tr[y].le,w);
    else Build(mid+1,r,tr[x].ri,tr[y].ri,w);
}
inline int Query(RG int l,RG int r,RG int tr1,RG int tr2,RG int tr3,RG int tr4,RG int w){
    if(l==r) return yyb[l];
    RG int mid=(l+r)>>1;
    RG int sum=tr[tr[tr1].le].w+tr[tr[tr2].le].w-tr[tr[tr3].le].w-tr[tr[tr4].le].w;
    if(w<=sum) return Query(l,mid,tr[tr1].le,tr[tr2].le,tr[tr3].le,tr[tr4].le,w);
    else return Query(mid+1,r,tr[tr1].ri,tr[tr2].ri,tr[tr3].ri,tr[tr4].ri,w-sum);
}

inline void Orz(){
    sort(yyb+1,yyb+1+n);
    len=unique(yyb+1,yyb+1+n)-yyb-1;
    for(RG int i=1;i<=n;++i) a[i]=lower_bound(yyb+1,yyb+1+len,a[i])-yyb;
}
inline void Insert(RG int x,RG int y) { s[++top]=(joker) { first[x],y },first[x]=top; }
inline void Dfs(RG int k,RG int fa){
    f[k][0]=fa,dep[k]=dep[fa]+1,Build(1,n,root[k],root[fa],a[k]);
    for(RG int i=1;i<=19;++i) f[k][i]=f[f[k][i-1]][i-1];
    for(RG int i=first[k];i;i=s[i].nxt){
        RG int en=s[i].en;
        if(en==fa) continue ;
        Dfs(en,k);
    } return ;
}

inline int Lca(RG int x,RG int y){
    if(dep[x]<dep[y]) swap(x,y);
    for(RG int i=19;i>=0;--i)
        if(dep[f[x][i]]>=dep[y])
            x=f[x][i];
    if(x==y) return x;
    for(RG int i=19;i>=0;--i)
        if(f[x][i]!=f[y][i])
            x=f[x][i],y=f[y][i];
    return f[x][0];
}

int main(){
    n=read(),m=read();
    for(RG int i=1;i<=n;++i) a[i]=yyb[i]=read();
    for(RG int i=1;i<n;++i){
        RG int x=read(),y=read();
        Insert(x,y),Insert(y,x);
    }   Orz(),Dfs(1,0); RG int ans=0;
    for(RG int i=1;i<=m;++i){
        RG int x=read()^ans,y=read(),k=read();
        RG int lca=Lca(x,y);
        printf("%d\n",ans=Query(1,n,root[x],root[y],root[lca],root[f[lca][0]],k));
    }
}

猜你喜欢

转载自blog.csdn.net/Love_mona/article/details/79802679