【Bzoj2588】Count on a tree

題意

偉大的樹上權值第k小。


解析

在樹上建立主席樹,每個點的前驅不再是它的前一個點,而是它的父親結點。我們可以這樣來想,序列上的主席樹類似於前綴和,用的時候直接序列上差分。而樹上也就可以把每個點保存爲到根的主席樹,查詢的時候也類比樹上的差分就可以了。


記得是Query(rt[x],rt[y]….)。

#include <cstdio>
#include <algorithm>

#define Rep( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i<=(i##_END);i++)
#define For( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i!=(i##_END);i++)
#define Lop( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i>=(i##_END);i--)
#define Dnt( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i!=(i##_END);i--)

using std :: max;
using std :: min;

const int maxx = 100000 + 25;

typedef int Array[maxx];

int n,m,x,y,z,tot,cnt,num,lastans,Totnum;
int head[maxx],to[maxx<<1],nxt[maxx<<1];
int rt[maxx],lc[maxx*20],rc[maxx*20],T[maxx*20];

Array a,b,v,top,dpt,son,ftr,rnk,size;

namespace Pre_Tree{

    void insert(int &i,int pre,int l,int r,int pos){
        T[i=++cnt] = T[pre] + 1;
        if(l == r) return;
        lc[i] = lc[pre];rc[i] = rc[pre];
        int mid = (l+r) >> 1;
        if(pos <= mid) insert(lc[i],lc[pre],l,mid,pos);
        if(pos >  mid) insert(rc[i],rc[pre],mid+1,r,pos);
    }

    int Query(int x,int y,int L,int Fl,int l,int r,int k){
        if(l == r) return l;
        int mid = (l+r) >> 1;
        int tmp = T[lc[x]] + T[lc[y]] - T[lc[L]] - T[lc[Fl]];
        if(tmp <  k) return Query(rc[x],rc[y],rc[L],rc[Fl],mid+1,r,k - tmp);
        if(tmp >= k) return Query(lc[x],lc[y],lc[L],lc[Fl],l,mid,k) ;
    }

}

using namespace Pre_Tree;

namespace Cute{

    void Ins(int x,int y){
        to[++num] = y;nxt[num] = head[x];head[x] = num;
    }

    void Dfs(int x){
        size[x] = 1;
        insert(rt[x],rt[ftr[x]],1,Totnum,v[x]);
        for(int i=head[x];i;i=nxt[i]){
            if(to[i] == ftr[x]) continue;
            dpt[to[i]] = dpt[x] + 1;
            ftr[to[i]] = x;
            Dfs(to[i]);size[x] += size[to[i]];
            if(size[to[i]] > size[son[x]]) son[x] = to[i];
        }
    }

    void __Dfs(int x,int brn){
        rnk[x] = ++tot;top[x] = brn;
        if(son[x]) __Dfs(son[x],brn);
        for(int i=head[x];i;i=nxt[i])
            if(to[i] != son[x] && to[i] != ftr[x])
                __Dfs(to[i],to[i]);
    }

    int Lca(int x,int y){
        while(top[x] != top[y]){
            if(dpt[top[x]] > dpt[top[y]]) std :: swap(x,y);
            y = ftr[top[y]];
        }
        return dpt[x] < dpt[y]? x : y;
    }

}

using namespace Cute;

int main(){
    scanf("%d%d",&n,&m);
    Rep( i , 1 , n ) scanf("%d",&a[i]),b[i] = a[i];
    std :: sort(b+1,b+n+1);
    Totnum = std :: unique(b+1,b+n+1) - b - 1;
    Rep( i , 1 , n ) v[i] = std :: lower_bound(b+1,b+Totnum+1,a[i]) - b;
    For( i , 1 , n ) scanf("%d%d",&x,&y),Ins(x,y),Ins(y,x);
    Dfs(1);__Dfs(1,1);
    while( m-- ){
        scanf("%d%d%d",&x,&y,&z);
        x ^= lastans;
        lastans = b[Query(rt[x],rt[y],rt[Lca(x,y)],rt[ftr[Lca(x,y)]],1,Totnum,z)];
        printf("%d",lastans);
        if(m != 0) putchar(10);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章