• 【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
    ",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
    ",last=getK(u,v,k-1));
            else printf("%d",getK(u,v,k-1));
        }
        return 0;
    }
    

      

  • 相关阅读:
    Java 给Word指定字符串添加批注
    Java 打印Word文档
    Java 在PDF中添加页面跳转按钮
    C# 添加、修改、删除Excel图表数据标签
    C# 添加、读取、删除Excel文档属性
    Java 操作Word表格——创建嵌套表格、添加/复制表格行或列、设置表格是否禁止跨页断行
    【Luogu5348】密码解锁(莫比乌斯反演,数论)
    AtCoder Grand Contest 015
    AtCoder Grand Contest 014
    Codeforces Round #556 (Div. 1)
  • 原文地址:https://www.cnblogs.com/chadinblog/p/6428620.html
Copyright © 2020-2023  润新知