zoukankan      html  css  js  c++  java
  • BZOJ1901 Dynamic Rankings|带修主席树

    题目链接:戳我

    其实我并不会做,于是看了题解

    我们都知道主席树是利用前缀和记录历史版本来搞区间K大的一种数据结构。不过一般的主席树只能搞定静态区间第K大。如果带修怎么办呢?

    想一下。。。单点修改+区间查询,我们是否能想到树状数组呢?

    那么思路就出来了。用树状数组来维护主席树的前缀和!!这里的主席树只需要维护对于每个节点所包含的值域区间中数的个数即可,不需要继承历史版本。

    单次操作复杂度两个log,应该是稳稳的了。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    inline int read()
    {
        int f=1,x=0; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48); ch=getchar();}
        return x*f;
    }
    int n,m,q_cnt,cnt,tot,cnt1,cnt2;
    int a[MAXN],S[MAXN],rt[MAXN],tmp1[MAXN],tmp2[MAXN];
    struct Node{int l,r,k,pos,t;}q[MAXN];
    struct Node2{int ls,rs,v;}t[MAXN<<5];
    inline void modify(int &now,int l,int r,int pos,int k)
    {
        if(!now) now=++tot;
        t[now].v+=k;
        if(l==r) return;
        int mid=(l+r)>>1;
        if(pos<=mid) modify(t[now].ls,l,mid,pos,k);
        else modify(t[now].rs,mid+1,r,pos,k);
    }
    inline void pre_modify(int x,int k)
    {
        int pos=lower_bound(&S[1],&S[1+cnt],a[x])-S;
        for(int i=x;i<=n;i+=i&(-i))
            modify(rt[i],1,cnt,pos,k);
    }
    inline int query(int l,int r,int k)
    {
        if(l==r) {return S[l];}
        int cur_ans=0;
        for(int i=1;i<=cnt1;i++) cur_ans+=t[t[tmp1[i]].ls].v;
        for(int i=1;i<=cnt2;i++) cur_ans-=t[t[tmp2[i]].ls].v;
        int mid=(l+r)>>1;
        if(cur_ans>=k)
        {
            for(int i=1;i<=cnt1;i++) tmp1[i]=t[tmp1[i]].ls;
            for(int i=1;i<=cnt2;i++) tmp2[i]=t[tmp2[i]].ls;
            return query(l,mid,k);
        }
        else 
        {
            for(int i=1;i<=cnt1;i++) tmp1[i]=t[tmp1[i]].rs;
            for(int i=1;i<=cnt2;i++) tmp2[i]=t[tmp2[i]].rs;
            return query(mid+1,r,k-cur_ans);
        }
    }
    inline void pre_query(int l,int r,int k)
    {
        cnt1=cnt2=0;
        for(int i=r;i;i-=i&(-i)) tmp1[++cnt1]=rt[i];
        for(int i=l;i;i-=i&(-i)) tmp2[++cnt2]=rt[i];
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) a[i]=read(),S[++cnt]=a[i];
        for(int i=1;i<=m;i++)
        {
            char cur[10];
            scanf("%s",cur);
            if(cur[0]=='Q') q[i]=(Node){read()-1,read(),read(),0,0};
            else q[i]=(Node){0,0,0,read(),read()},S[++cnt]=q[i].t;
        }
        sort(&S[1],&S[cnt+1]);
        cnt=unique(&S[1],&S[cnt+1])-S-1;
        for(int i=1;i<=n;i++) pre_modify(i,1);
        for(int i=1;i<=m;i++)
        {
            if(q[i].k!=0)
            {
                pre_query(q[i].l,q[i].r,q[i].k);
                printf("%d
    ",query(1,cnt,q[i].k));
            }
            else
            {
                pre_modify(q[i].pos,-1);
                a[q[i].pos]=q[i].t;
                pre_modify(q[i].pos,1);
            }
        }
    }
    
  • 相关阅读:
    mysql常用基本命令
    mysql8.0.13下载与安装图文教程
    k8s ingress 增加跨域配置
    Jenkins 备份恢复插件 thinBackup 使用
    k8s HA master 节点宕机修复
    nginx 跨域问题解决
    mongodb 3.4.24 主从复制
    k8s 线上安装 jenkins并结合 jenkinsfile 实现 helm 自动化部署
    k8s helm 运用与自建helm仓库chartmuseum
    centos6 源码安装 unzip
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10308857.html
Copyright © 2011-2022 走看看