[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\n",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\n",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\n",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\n",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\n",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\n",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\n",sum[c[c[rt][1]][0]]);
        }
        else
        {
            split(1,n);u=c[c[rt][1]][0];
            printf("%d\n",s[u].mid);
        }
        // dfs(rt);
    }
    return 0;
}

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

 

posted @ 2017-03-08 22:05  FallDream  阅读(669)  评论(0编辑  收藏  举报