• 动态主席树 优化版


    和大奕哥一起学习了主席树,机房里杰哥看了之后一直说可以优化空间,题解写的太low了,所以我今天写了一个动态开点的线段树来优化一波空间,bz上试了一下,确实比网上看的题解省空间。

    网上的题解是每一次都新开点,是可持久化的写法,我写的是正经的线段树动态开点。

    ——by VANE

    附上代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=10010,INF=1e9+10;
    int n,m,pl,tl,mx;
    int a[N<<1],num[N<<1],crt[N<<1];
    char s[10];
    struct tnode
    {
        int lc,rc,cnt;
    }t[N*120];
    struct ques
    {
        int l,r,k,x,d;
        bool tmp;
    }q[N];
    struct node
    {
        int d,id;
    }p[N<<1];
    bool cmp(node x,node y) {return x.d<y.d;}
    void merge(int x)
    {
        t[x].cnt=t[t[x].lc].cnt+t[t[x].rc].cnt;
    }
    void update(int &rt,int p,int d,int l,int r)
    {
        if(!rt) rt=++tl;
        if(l==r)
        {
            t[rt].cnt+=d;
            return;
        }
        int mid=l+r>>1;
        if(p<=mid) update(t[rt].lc,p,d,l,mid);
        else update(t[rt].rc,p,d,mid+1,r);
        merge(rt);
    }
    void add(int x,int p,int d)
    {
        for(int i=x;i<=n;i+=i&-i) update(i,p,d,1,mx);
    }
    int getsum(int x)
    {
        int ans=0;
        for(int i=x;i;i-=i&-i) ans+=t[t[crt[i]].lc].cnt;
        return ans;
    }
    int query(int lx,int rx,int k)
    {
        for(int i=lx-1;i>=1;i-=(i&(-i))) crt[i]=i;
        for(int i=rx;i>=1;i-=(i&(-i))) crt[i]=i;
        int l=1,r=mx,mid,sum;
        while(l<r)
        {
            mid=(l+r)/2;
            sum=getsum(rx)-getsum(lx-1);
            if(sum>=k)
            {
                r=mid;
                for(int i=lx-1;i>=1;i-=(i&(-i))) crt[i]=t[crt[i]].lc;
                for(int i=rx;i>=1;i-=(i&(-i))) crt[i]=t[crt[i]].lc;
            }
            else
            {
                l=mid+1;
                k-=sum;
                for(int i=lx-1;i>=1;i-=(i&(-i))) crt[i]=t[crt[i]].rc;
                for(int i=rx;i>=1;i-=(i&(-i))) crt[i]=t[crt[i]].rc;
            }
        }
        return l;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        pl=n;tl=n;
        for(int i=1;i<=n;i++) 
        {
            scanf("%d",&a[i]);
            p[i].d=a[i];p[i].id=i;
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%s",s);
            if(s[0]=='Q') 
            {
                q[i].tmp=0;
                scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);
            }
            else
            {
                q[i].tmp=1;
                scanf("%d%d",&q[i].x,&q[i].d);
                p[++pl].d=q[i].d;p[pl].id=n+i;
            }
        }
        sort(p+1,p+1+pl,cmp);
        mx=0;p[0].d=INF;
        for(int i=1;i<=pl;i++)
        {
            if(p[i].d!=p[i-1].d) mx++,num[mx]=p[i].d;
            if(p[i].id<=n) a[p[i].id]=mx;
            else q[p[i].id-n].d=mx;
        }
        for(int i=1;i<=n;i++) 
            add(i,a[i],1);
        for(int i=1;i<=m;i++)
        {
            if(q[i].tmp==0)
                printf("%d
    ",num[query(q[i].l,q[i].r,q[i].k)]);
            else
            {
                add(q[i].x,a[q[i].x],-1);
                add(q[i].x,q[i].d,1);
                a[q[i].x]=q[i].d;
            }
        }
        return 0;
    }
  • 相关阅读:
    震旦199打印机扫描A4文件
    震旦199打印机使用“多组多张文件”复印功能
    局域网电脑快速添加共享的打印机
    打印机连续打印,速度变慢,打印队列一直自动闪烁
    用IntelliJ IDEA编译,编译之后提示 无效的标记: -release
    hao360恶意篡改IE首页——修复方法
    联想一体机怎么设置u盘启动|联想一体机bios改U盘启动方法(转)
    解决局域网IP冲突
    Cisco Packet Tracer 交换机 2950-24 配置
    静态路由作用和添加删除命令
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8012149.html
Copyright © 2020-2023  润新知