zoukankan      html  css  js  c++  java
  • BZOJ1500:[NOI2005]维修数列——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=1500

    https://www.luogu.org/problemnew/show/P2042#sub

    请写一个程序,要求维护一个数列,支持以下 6 种操作:
    请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格

    太神啦太神啦,我也不会做,我也是copycat的啊。

    https://www.luogu.org/blog/IAmHellWord/solution-p2042

    直接看上面这位神犇的题解吧。

    #include<cstdio>
    #include<queue>
    #include<cctype>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int N=1e6+10;
    const int INF=1e9;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    char s[101];
    int fa[N],tr[N][2],key[N],size[N],mx[N];
    int root,sz,a[N],id[N],sum[N],lx[N],rx[N];
    bool rev[N],tag[N];
    queue<int>q;
    inline void pushup(int x){
        int l=tr[x][0],r=tr[x][1];
        sum[x]=sum[l]+sum[r]+key[x];
        size[x]=size[l]+size[r]+1;
        mx[x]=max(mx[l],max(mx[r],rx[l]+key[x]+lx[r]));
        lx[x]=max(lx[l],sum[l]+key[x]+lx[r]);
        rx[x]=max(rx[r],sum[r]+key[x]+rx[l]);
    }
    inline void pushdown(int x){
        int l=tr[x][0],r=tr[x][1];
        if(tag[x]){
            rev[x]=tag[x]=0;
            if(l)tag[l]=1,key[l]=key[x],sum[l]=key[x]*size[l];
            if(r)tag[r]=1,key[r]=key[x],sum[r]=key[x]*size[r];
            if(key[x]>=0){
                if(l)lx[l]=rx[l]=mx[l]=sum[l];
                if(r)lx[r]=rx[r]=mx[r]=sum[r];
            }else{
                if(l)lx[l]=rx[l]=0,mx[l]=key[x];
                if(r)lx[r]=rx[r]=0,mx[r]=key[x];
            }
        }
        if(rev[x]){
            rev[x]=0;rev[l]^=1;rev[r]^=1;
            swap(lx[l],rx[l]);swap(lx[r],rx[r]);
            swap(tr[l][0],tr[l][1]);swap(tr[r][0],tr[r][1]);
        }
    }
    inline bool get(int x){
        return tr[fa[x]][1]==x;
    }
    inline void rotate(int x){
        int y=fa[x],z=fa[y],which=get(x);
        tr[y][which]=tr[x][which^1];fa[tr[y][which]]=y;  
        fa[y]=x;tr[x][which^1]=y;fa[x]=z;
        if(z)tr[z][tr[z][1]==y]=x;
        pushup(y);pushup(x);
        return;
    }
    inline void splay(int x,int y){
        int f=fa[x];
        while(f!=y){
        if(fa[f]!=y)rotate(get(x)==get(f)?f:x);
        rotate(x);f=fa[x];
        }
        if(!y)root=x;
        return;
    }
    inline int findx(int x){//找到排名为x的点
        int now=root;
        while(233){
        pushdown(now);
            if(tr[now][0]&&x<=size[tr[now][0]])now=tr[now][0];
            else{
                int temp=(tr[now][0]?size[tr[now][0]]:0)+1;
                if(x==temp)return now;
                x-=temp;now=tr[now][1];
            }
        }
    }
    inline int split(int k,int tot){
        int x=findx(k),y=findx(k+tot+1);
        splay(x,0);splay(y,x);
        return tr[y][0];
    }
    inline void query(int k,int tot){
        int x=split(k,tot);
        printf("%d
    ",sum[x]);
    }
    inline void modify(int k,int tot,int v){
        int x=split(k,tot),y=fa[x];
        key[x]=v;tag[x]=1;sum[x]=size[x]*v;
        if(v>=0)lx[x]=rx[x]=mx[x]=sum[x];
        else lx[x]=rx[x]=0,mx[x]=v;
        pushup(y);pushup(fa[y]);
    }
    inline void turn(int k,int tot){
        int x=split(k,tot),y=fa[x];
        if(!tag[x]){
        rev[x]^=1;
        swap(tr[x][0],tr[x][1]);
        swap(lx[x],rx[x]);
        pushup(y);pushup(fa[y]);
        }
        return;
    }
    inline void recycle(int x){
        int &l=tr[x][0],&r=tr[x][1];
        if(l)recycle(l);
        if(r)recycle(r);
        q.push(x);
        fa[x]=l=r=tag[x]=rev[x]=0;
    }
    inline void build(int l,int r,int f){
        int mid=(l+r)>>1,now=id[mid],pre=id[f];
        if(l==r){
        mx[now]=sum[now]=a[l];
        tag[now]=rev[now]=0;
        lx[now]=rx[now]=max(a[l],0);
        size[now]=1;
        }
        if(l<mid)build(l,mid-1,mid);
        if(mid<r)build(mid+1,r,mid);
        key[now]=a[mid],fa[now]=pre;
        pushup(now);
        tr[pre][mid>=f]=now;
    }
    inline void insert(int k,int tot){
        for(int i=1;i<=tot;i++)a[i]=read();
        for(int i=1;i<=tot;i++){
        if(!q.empty())id[i]=q.front(),q.pop();
        else id[i]=++sz;
        }
        build(1,tot,0);
        int z=id[(1+tot)>>1];
        int x=findx(k+1),y=findx(k+2);
        splay(x,0);splay(y,x);
        fa[z]=y;tr[y][0]=z;
        pushup(y);pushup(x);
        return;
    }
    inline void del(int k,int tot){
        int x=split(k,tot),y=fa[x];
        recycle(x);tr[y][0]=0;
        pushup(y);pushup(fa[y]);
        return;
    }
    int main(){
        int n=read(),m=read();
        mx[0]=a[1]=a[n+2]=-INF;
        for(int i=2;i<=n+1;i++)a[i]=read();
        for(int i=1;i<=n+2;i++)id[i]=i;
        build(1,n+2,0);
        root=(n+3)>>1;sz=n+2;
        for(int i=1;i<=m;i++){
        scanf("%s",s);
        if(s[0]=='I'){
            int k=read(),tot=read();
            insert(k,tot);
        }
        if(s[0]=='D'){
            int k=read(),tot=read();
            del(k,tot);
        }
        if(s[0]=='M'){
            if(s[2]=='X')printf("%d
    ",mx[root]);
            else{
            int k=read(),tot=read(),c=read();
            modify(k,tot,c);
            }
        }
        if(s[0]=='R'){
            int k=read(),tot=read();
            turn(k,tot);
        }
        if(s[0]=='G'){
            int k=read(),tot=read();
            query(k,tot);
        }
        }
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    【重构学习】12 重构学习感想
    【重构学习】11 大型重构
    【重构学习】10 继承关系的重构
    【重构学习】09 函数调用的重构
    【重构学习】08 条件表达式的重构
    嵊州D4T1 翻车 rollover 真的翻车了
    计算圆内格点数
    嵊州D3T2 福尔贝斯太太的快乐夏日 summer
    嵊州D3T3 light
    嵊州D3T1 山魔 烙饼问题
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8672180.html
Copyright © 2011-2022 走看看