• [bzoj1500][NOI2005]维修数列


    最近看一位大佬狂刷平衡树,怒淦维修数列,自己好久没写splay了,而且也不难,就去做了做。

    几下写完了模板,调了调感觉无比正确, 然后交上去无限TLE,以为是写的丑,就一直乱调。

    最后发现是回收内存时候的数组忘了清空了,就这东西调了一晚上.....啊啊啊啊啊我要疯啦

    题意:需要你维护一个数列的很多种操作:  数字不会超过500000个,操作<=20000,插入的数不超过四百万

    题解:splay裸题,瞎维护。整道题其实就只有最后一个问题比较坑。

    每个点维护从最左边开始的最大值,从最右边开始的最大值,和中间的最大值,像线段树那样子合并。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define MAXN 500000
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    bool rev[MAXN+5],mark[MAXN+5];
    int fa[MAXN+5],size[MAXN+5],sum[MAXN+5];
    int c[MAXN+5][2],ad[MAXN+5],num[MAXN+5];
    queue<int> q;int id[MAXN+5];
    int n,m,rt,tot,pos,u,v;
    char op[50];
    struct data{
        int l,r,mid;
    }s[MAXN+5];
    
    void update(int k)
    {
        //   printf("update%d
    ",k);
        int l=c[k][0],r=c[k][1];
        sum[k]=sum[l]+sum[r]+num[k];
        size[k]=size[l]+size[r]+1;
        if(!l&&!r){s[k]=(data){num[k],num[k],num[k]};return;}
        s[k].l=s[k].r=s[k].mid=-INF;
        if(l){s[k].l=s[l].l;s[k].mid=max(s[k].mid,s[l].mid);}
        if(r){s[k].r=s[r].r;s[k].mid=max(s[k].mid,s[r].mid);}
        s[k].l=max(s[k].l,sum[l]+num[k]+(s[r].l>0?s[r].l:0));
        s[k].r=max(s[k].r,sum[r]+num[k]+(s[l].r>0?s[l].r:0));
        s[k].mid=max(s[k].mid,(s[l].r>0?s[l].r:0)+num[k]+(s[r].l>0?s[r].l:0));
    }
    
    void pushdown(int k)
    {
        //  printf("pushdown%d
    ",k);
        int l=c[k][0],r=c[k][1];
        if(rev[k])
        {
            swap(c[k][0],c[k][1]);swap(s[l].l,s[l].r);swap(s[r].l,s[r].r);
            rev[k]^=1;rev[l]^=1;rev[r]^=1;
            update(k);
        }
        if(mark[k])
        {
            sum[l]=ad[k]*size[l];
            sum[r]=ad[k]*size[r];
            mark[k]=0;mark[l]=1;mark[r]=1;
            ad[l]=ad[r]=num[l]=num[r]=ad[k];
            if(ad[k]>0)s[l]=(data){sum[l],sum[l],sum[l]},s[r]=(data){sum[r],sum[r],sum[r]};
            else s[l]=(data){ad[k],ad[k],ad[k]},s[r]=(data){ad[k],ad[k],ad[k]};
            ad[k]=0;
        }
    }
    
    void rotate(int x,int &k)
    {
        //  printf("rotate%d %d
    ",x,k);
        int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
        if(y==k) k=x;
        else c[z][c[z][1]==y]=x;
        fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
        c[y][l]=c[x][r];c[x][r]=y;
        update(y);update(x);
    }
    
    void splay(int x,int&k)
    {
        //  printf("splay%d %d
    ",x,k);
        while(x!=k)
        {
            int y=fa[x],z=fa[y];
            if(y!=k)
            {
                if(c[z][0]==y^c[y][0]==x)rotate(x,k);
                else rotate(y,k);
            }
            rotate(x,k);
        }
    }
    
    int find(int x,int rk)
    {
        // printf("find%d %d
    ",x,rk);
        pushdown(x);
        int l=c[x][0],r=c[x][1];
        if(size[l]>=rk)return find(l,rk);
        if(size[l]+1<rk)return find(r,rk-size[l]-1);
        return x;
    }
    
    void split(int l,int r)
    {
        splay(find(rt,l),rt);
        splay(find(rt,r),c[rt][1]);
    }
    
    void build(int&x,int l,int r,int last)
    {
        if(l>r)return;
        x=q.front();q.pop();fa[x]=last;
        int mid=(l+r)>>1;
        size[x]=1;num[x]=id[mid];rev[x]=mark[x]=ad[x]=0;
        build(c[x][0],l,mid-1,x);
        build(c[x][1],mid+1,r,x);
        update(x);
    }
    
    void init(int&x,int l,int r,int last)
    {
        if(l>r)return;
        x=(l+r)>>1;fa[x]=last;
        size[x]=1;num[x]=id[x];rev[x]=mark[x]=ad[x]=0;
        init(c[x][0],l,x-1,x);
        init(c[x][1],x+1,r,x);
        update(x);
    }
    
    void reuse(int x)
    {
        if(!x)return;
        if(c[x][0])reuse(c[x][0]);
        if(c[x][1])reuse(c[x][1]);
        q.push(x);c[x][0]=c[x][1]=fa[x]=0;
    }
    /*
     void dfs(int x)
     {
     printf("%d %d %d %d %d %d %d %d %d %d
    ",x,fa[x],c[x][0],c[x][1],size[x],num[x],sum[x],s[x].l,s[x].r,s[x].mid);
     if(c[x][0])dfs(c[x][0]);
     if(c[x][1])dfs(c[x][1]);
     }
     */
    
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)id[i+1]=read();
        for(int i=n+3;i<=500002;i++)q.push(i);
        n+=2;init(rt,1,n,rt);
        for(int i=1;i<=m;i++)
        {
            scanf("%s",op+1);
            if(op[1]=='I')
            {
                pos=read();tot=read();for(int i=1;i<=tot;i++)id[i]=read();
                split(pos+1,pos+2);build(c[c[rt][1]][0],1,tot,c[rt][1]);
                fa[c[c[rt][1]][0]]=c[rt][1];update(c[rt][1]);update(rt);n+=tot;
            }
            else if(op[1]=='D')
            {
                pos=read();tot=read();split(pos,pos+tot+1);
                reuse(c[c[rt][1]][0]);c[c[rt][1]][0]=0;
                update(c[rt][1]);update(rt);n-=tot;
            }
            else if(op[1]=='M'&&op[3]=='K')
            {
                pos=read();tot=read();u=read();split(pos,pos+tot+1);
                v=c[c[rt][1]][0];sum[v]=size[v]*u;mark[v]=1;ad[v]=u;num[v]=u;
                if(u>=0)s[v]=(data){sum[v],sum[v],sum[v]};
                else s[v]=(data){u,u,u};
                update(c[rt][1]);update(rt);
            }
            else if(op[1]=='R')
            {
                pos=read();tot=read();split(pos,pos+tot+1);
                v=c[c[rt][1]][0];rev[v]^=1;swap(s[v].l,s[v].r);
                update(c[rt][1]);update(rt);
            }
            else if(op[1]=='G')
            {
                pos=read();tot=read();split(pos,pos+tot+1);
                printf("%d
    ",sum[c[c[rt][1]][0]]);
            }
            else
            {
                split(1,n);u=c[c[rt][1]][0];
                printf("%d
    ",s[u].mid);
            }
            // dfs(rt);
        }
        return 0;
    }

    啊啊啊啊啊我真的要疯了(不能疯,你还没有写作业)

  • 相关阅读:
    fork()和僵尸进程
    布尔变量面试题
    vue学习之二
    vue学习之一
    圈复杂度
    phpExcel与jq的ajax
    Object.defineProperty与修改某个数组实现监听效果
    mpn不得不说的坑
    论javascript编写优美
    微信小程序之学习
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj1500.html
Copyright © 2020-2023  润新知