[bzoj2588]Count on a tree-the chairman tree on the tree

Main idea of the title:

Given a tree, ask for the value of the smallest k of the weight of the point in the path on (x,y)(x,y).

Train of thought:

It can be maintained by a chairman tree, which is actually similar to a tree difference. Think about the chairman tree static query interval k hour using r's weighted line segment tree minus l-1's weighted line segment tree. Similarly, we put all the points from the node to the root into a weight segment tree, and then we can replace it with the weight segment tree of 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;
}

Posted by Grimloch on Mon, 04 Feb 2019 02:21:15 -0800