zoukankan      html  css  js  c++  java
  • 洛谷 P2042[NOI2005]维护数列 (平衡树)

    传送门

    平衡树裸题##

    为了熟悉一下平衡树,来做了一下这道码农题,
    虽然辛苦,但确实对 (FhqTreap) 的理解加深了不少。
    下面贴上没有优化,开了 (O2) 和各种卡常勉强过去的代码

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    using namespace std;
    typedef long long LL;
    const int MAXN=5000010;
    const int inf=0x3f3f3f3f;
    const LL INF=0x3f3f3f3f3f3f3f3f;
    int n,m;
    
    inline int read(){
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    struct FhqTreap{
        int L[MAXN],R[MAXN],tag[MAXN],rev[MAXN],siz[MAXN],key[MAXN],tot,root;
        int val[MAXN],sum[MAXN],lx[MAXN],rx[MAXN],mx[MAXN];
    
        inline int newnode(int value){
            //cout<<value<<endl;
            tag[++tot]=inf,val[tot]=value,sum[tot]=value,siz[tot]=1,key[tot]=rand();
            if(value>0) lx[tot]=rx[tot]=mx[tot]=value;
            else lx[tot]=rx[tot]=0,mx[tot]=value;
            return tot;
        }
    
        inline void pushdown(int id){
            if(tag[id]!=inf){
                sum[L[id]]=tag[id]*siz[L[id]],val[L[id]]=tag[L[id]]=tag[id];
                sum[R[id]]=tag[id]*siz[R[id]],val[R[id]]=tag[R[id]]=tag[id];
                if(tag[id]>0) 
                    lx[L[id]]=rx[L[id]]=mx[L[id]]=sum[L[id]],
                    lx[R[id]]=rx[R[id]]=mx[R[id]]=sum[R[id]];
                else
                    lx[L[id]]=rx[L[id]]=lx[R[id]]=rx[R[id]]=0,
                    mx[L[id]]=mx[R[id]]=tag[id];
                tag[id]=inf;
                rev[id]=0;
            }
            if(rev[id]){
                swap(L[L[id]],R[L[id]]),swap(lx[L[id]],rx[L[id]]);
                swap(L[R[id]],R[R[id]]),swap(lx[R[id]],rx[R[id]]);
                rev[L[id]]^=1,rev[R[id]]^=1;
                rev[id]=0;
            }
        }
    
        inline void pushup(int id){
            siz[id]=siz[L[id]]+siz[R[id]]+1;
            sum[id]=sum[L[id]]+sum[R[id]]+val[id];
            lx[id]=max(lx[L[id]],sum[L[id]]+val[id]+lx[R[id]]);
            rx[id]=max(rx[R[id]],sum[R[id]]+val[id]+rx[L[id]]);
            mx[id]=max(max(mx[L[id]],mx[R[id]]),rx[L[id]]+lx[R[id]]+val[id]);
        }
    
        inline void split(int id,int size,int &x,int &y){
            if(!id) x=y=0;
            else{
                pushdown(id);
                if(size>siz[L[id]])
                    x=id,split(R[id],size-siz[L[id]]-1,R[id],y);
                else   
                    y=id,split(L[id],size,x,L[id]);
                pushup(id);
            }
        }
    
        inline int merge(int x,int y){
            if(!x||!y) return x+y;
            if(key[x]>key[y]){
                pushdown(x);
                R[x]=merge(R[x],y);
                pushup(x);
                return x;
            }
            else{
                pushdown(y);
                L[y]=merge(x,L[y]);
                pushup(y);
                return y;
            }
        }
    
        inline void insert(){
            int ins=0,pos=read(),num=read();
            for(register int i=1;i<=num;i++) ins=merge(ins,newnode(read()));
            int x,y;
            split(root,pos,x,y);
            root=merge(merge(x,ins),y);
        }
    
        inline void del(){
            int pos=read(),num=read();
            int x,y,z;
            split(root,pos-1,x,y);
            split(y,num,y,z);
            root=merge(x,z);
        }
    
        inline void update(){
            int pos=read(),num=read(),value=read();
            int x,y,z;
            split(root,pos-1,x,y);
            split(y,num,y,z);
            sum[y]=1ll*value*siz[y];
            val[y]=tag[y]=value;
            if(value>0) lx[y]=rx[y]=mx[y]=sum[y];
            else lx[y]=rx[y]=0,mx[y]=value;
            root=merge(merge(x,y),z);
        }
    
        inline void reverse(){
            int pos=read(),num=read();
            int x,y,z;
            split(root,pos-1,x,y);
            split(y,num,y,z);
            rev[y]^=1;
            swap(L[y],R[y]),swap(lx[y],rx[y]);
            root=merge(merge(x,y),z);
        }
    
        inline void getsum(){
            int pos=read(),num=read(),x,y,z;
            split(root,pos-1,x,y);
            split(y,num,y,z);
            printf("%d
    ",sum[y]);
            root=merge(merge(x,y),z);
        }
    
        inline void maxsum(){
            printf("%d
    ",mx[root]);
        }
    }fhq;
    
    
    int main(){
        srand(time(0));
        n=read(),m=read();
        for(register int i=1;i<=n;i++)
            fhq.root=fhq.merge(fhq.root,fhq.newnode(read()));
        char opt[20];
        while(m--){
            scanf("%s",opt);
            if(opt[0]=='I') fhq.insert();
            else if(opt[0]=='D') fhq.del();
            else if(opt[0]=='R') fhq.reverse();
            else if(opt[0]=='G') fhq.getsum();
            else if(opt[0]=='M'&&opt[2]=='K') fhq.update();
            else if(opt[0]=='M'&&opt[2]=='X') fhq.maxsum();
        }
        return 0;
    }
    

    其实数组容量不需要开那么大, 有点太极限了, 贴着内存限制过去的
    题面上说了, 同时在数列中的数不超过 (5cdot 10^5) 那么可以搞一个 (queue),
    把删除之后的节点编号放进去, 就像一个内存回收器一样.

  • 相关阅读:
    mongoDB 获取系统时间
    android应用程序监听SMS Intent广播
    安卓开发之探秘蓝牙隐藏API
    Android内存优化解决 资料和总结的经验分享
    android 访问SMS短信收件箱
    Android 和 PHP 之间进行数据加密传输
    Android开发 MMS支持 创建和编辑MMS
    android 动态改变屏幕方向
    Android 使用 Gmail 来发送邮件
    android数据库操作之直接读取db文件
  • 原文地址:https://www.cnblogs.com/BakaCirno/p/11774869.html
Copyright © 2011-2022 走看看