【bzoj2588】Count on a tree 主席树

这题给人开了个新思路。

原本构造一个序列的主席树,是这个位置用上个位置的信息来省空间,树上的主席树是继承父亲的信息来省空间。

此题若带修改怎么办?

若对某个点的权值做修改,则这个点的子树都会受影响,想到了dfs序上的树状数组加差分套权值线段树,感觉很劲啊。

update:

好吧,带修改的树上第K大:bzoj1146,确实有这么一种做法。

/**************************************************************
    Problem: 2588
    User: chad
    Language: C++
    Result: Accepted
    Time:6236 ms
    Memory:57688 kb
****************************************************************/
 
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<map>
#include<queue>
using namespace std;
#define mem1(i,j) memset(i,j,sizeof(i))
#define mem2(i,j) memcpy(i,j,sizeof(i))
#define LL long long
#define up(i,j,n) for(LL i=(j);i<=(n);i++)
#define FILE "dealing"
#define poi vec
#define eps 1e-10
#define db double
#define mid ((l+r)>>1)
const int maxn=102000,inf=1000000000,mod=1000000007;
int read(){
    LL x=0,f=1,ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0',ch=getchar();}
    return f*x;
}
bool cmax(int& a,int b){return a<b?a=b,true:false;}
bool cmin(int& a,int b){return a>b?a=b,true:false;}
int n,m,L=1;
int fa[maxn][32],dep[maxn],v[maxn],t[maxn];
struct node{int y,next;}e[maxn<<1];int linkk[maxn<<1],len;
struct Node{int v,id;}a[maxn];
bool cmp(Node a,Node b){return a.v<b.v;}
bool cmp2(Node a,Node b){return a.id<b.id;}
void insert(int x,int y){e[++len].y=y;e[len].next=linkk[x];linkk[x]=len;}
int rt[2300000],cnt=0,sum[2300000],c[2300000][2];
int key=0;
void updata(int o){sum[o]=sum[c[o][1]]+sum[c[o][0]];}
void set(int& o,int x,int l,int r){
    o=++cnt;
    if(l==r){sum[o]=sum[x]+1;return;}
    if(key>mid)c[o][0]=c[x][0],set(c[o][1],c[x][1],mid+1,r);
    else c[o][1]=c[x][1],set(c[o][0],c[x][0],l,mid);
    updata(o);
}
void dfs(int x){
    key=v[x];set(rt[x],rt[fa[x][0]],1,L);
    for(int i=linkk[x];i;i=e[i].next){
        if(e[i].y==fa[x][0])continue;
        fa[e[i].y][0]=x;
        dep[e[i].y]=dep[x]+1;
        dfs(e[i].y);
    }
}
int lca(int x,int y){
    if(dep[x]>dep[y])swap(x,y);
    for(int i=28;i>=0;i--)if(dep[y]-dep[x]>=(1<<i))y=fa[y][i];
    if(x==y)return x;
    for(int i=28;i>=0;i--)if(fa[y][i]!=fa[x][i])x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
int q[10],val,bol[10]={0,1,1,-1,-1};
int query(int l,int r){
    if(l==r)return t[l];
    val=0;up(i,1,4)val+=bol[i]*sum[c[q[i]][0]];
    //printf("%d %d %d %d\n",l,r,sum[q[1]]+sum[q[2]]-sum[q[3]]-sum[q[4]],0);
    if(key>=val){
        key-=val;
        up(i,1,4)q[i]=c[q[i]][1];
        return query(mid+1,r);}
    else {
        up(i,1,4)q[i]=c[q[i]][0];
        return query(l,mid);
    }
}
int getK(int x,int y,int k){
    key=k;
    q[1]=rt[x],q[2]=rt[y],q[3]=rt[k=lca(x,y)],q[4]=rt[fa[k][0]];
    return query(1,L);
}
int main(){
    //freopen(FILE".in","r",stdin);
    //freopen(FILE".out","w",stdout);
    n=read(),m=read();
    up(i,1,n)a[i].v=read(),a[i].id=i;
    up(i,1,n-1){
        int x=read(),y=read();
        insert(x,y);insert(y,x);
    }
    sort(a+1,a+n+1,cmp);
    int j=1;
    while(true){
        t[L]=a[j].v;//离散权值的实际权值
        v[a[j].id]=L;j++;//j节点的离散权值
        if(j>n)break;
        if(a[j].v!=a[j-1].v)L++;
    }
    sort(a+1,a+n+1,cmp2);
    dfs(1);
    for(int j=1;j<=30;j++)
        for(int i=1;i<=n;i++)
            fa[i][j]=fa[fa[i][j-1]][j-1];
    int last=0;
    while(m--){
        int u=read(),v=read(),k=read();
        u^=last;
        if(m)printf("%d\n",last=getK(u,v,k-1));
        else printf("%d",getK(u,v,k-1));
    }
    return 0;
}

  

posted @ 2017-02-22 14:01  CHADLZX  阅读(89)  评论(0编辑  收藏  举报