[bzoj2588]Count on a tree——树上主席树 大佬们的博客 Some Links

题目大意:

给定一棵树,然后询问对于 ( x , y ) 上的路径中的点的权值第k小的值。

思路:

可以用主席树来维护,其实就类似一个树上差分。想一下主席树静态查询区间第k小时是用r的权值线段树减去l-1的权值线段树。这里也类似,我们把每一个结点从它到根的所有的点都放到一个权值线段树中,那么就可以用u+v-lca-fa[lca]的权值线段树来代替。

#include<bits/stdc++.h>

#define REP(i,a,b) for(int i=a;i<=b;++i)
typedef long long ll;

using namespace std;

void File(){
    freopen("bzoj2588.in","r",stdin);
    freopen("bzoj2588.out","w",stdout);
}

template<typename T>void read(T &_){
    T __=0,mul=1; char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')mul=-1;
        ch=getchar();
    }
    while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
    _=__*mul;
}

const int maxn=1e5+10;
int n,m,w[maxn],b[maxn],an[maxn][22],dep[maxn],tot;
int beg[maxn],to[maxn<<1],las[maxn<<1],cnte=1;
int root[maxn];

void add(int u,int v){
    las[++cnte]=beg[u]; beg[u]=cnte; to[cnte]=v;
    las[++cnte]=beg[v]; beg[v]=cnte; to[cnte]=u;
}

void dfs(int u,int f){
    dep[u]=dep[f]+1;
    an[u][0]=f;
    for(int i=beg[u];i;i=las[i]){
        if(to[i]==f)continue;
        dfs(to[i],u);
    }
}

int get_lca(int u,int v){
    if(dep[u]<dep[v])swap(u,v);
    for(int p=log(dep[u])/log(2);p>=0 && dep[u]!=dep[v];--p)
        if(dep[an[u][p]]>=dep[v])u=an[u][p];
    if(u==v)return u;
    for(int p=log(dep[u])/log(2);p>=0;--p){
        if(an[u][p]!=an[v][p])u=an[u][p],v=an[v][p];
    }
    return an[u][0];
}

struct Chairman_Tree{
#define mid ((l+r)>>1)
    int cnt;
    struct node{int lc,rc,sum;}a[maxn<<5];
    void insert(int &rt,int l,int r,int x){
        a[++cnt]=a[rt]; rt=cnt; ++a[rt].sum;
        if(l==r)return;
        if(x<=mid)insert(a[rt].lc,l,mid,x);
        else insert(a[rt].rc,mid+1,r,x);
    }
    int query(int u,int v,int lca,int f,int l,int r,int k){
        if(l==r)return l;
        int val=a[a[u].lc].sum+a[a[v].lc].sum-a[a[lca].lc].sum-a[a[f].lc].sum;
        if(k<=val)return query(a[u].lc,a[v].lc,a[lca].lc,a[f].lc,l,mid,k);
        else return query(a[u].rc,a[v].rc,a[lca].rc,a[f].rc,mid+1,r,k-val);
    }
}T;

void build(int u,int f){
    root[u]=root[f];
    int num=lower_bound(b+1,b+tot+1,w[u])-b;
    T.insert(root[u],1,tot,num);
    for(int i=beg[u];i;i=las[i]){
        if(to[i]==f)continue;
        build(to[i],u);
    }
}

void init(){
    read(n); read(m);
    REP(i,1,n)read(w[i]),b[i]=w[i];
    sort(b+1,b+n+1);
    tot=unique(b+1,b+n+1)-b-1;
    int u,v;
    REP(i,1,n-1){
        read(u); read(v);
        add(u,v);
    }
    dfs(1,0);
    REP(j,1,20)REP(i,1,n){
        if(dep[i]<=(1<<j))continue;
        an[i][j]=an[an[i][j-1]][j-1];
    }
    build(1,0);
}

void work(){
    int x,y,k,lasans=0;
    REP(i,1,m){
        read(x); read(y); read(k);
        x^=lasans;
        int lca=get_lca(x,y);
        lasans=T.query(root[x],root[y],root[lca],root[an[lca][0]],1,tot,k);
        lasans=b[lasans];
        printf("%d\n",lasans);
    }
}

int main(){
    File();
    init();
    work();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ylsoi/article/details/81635509