HYSBZ 1500 维修数列

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1500

操作1:把要插入的数字先建成一颗树,然后splay相应位置,直接将树连上去

操作2,3,4,5:都是splay普通操作

操作6:像维护线段树一样,同时维护max,maxl,maxr就行了

注意点:

旋转时maxl和maxr也要交换

要使用内存池,当弹出一个节点时,将它的两个子树丢进内存池中

same的值可能为0,所以要设为inf

max不能为空,所以初始应设成-inf,而不是0,否则update时会出错

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define lson i<<1
#define rson i<<1|1
using namespace std;
const int N=5e5+5;
const int inf=1e9;
int head,tail,q[N*10],root;
int a[N],b[N],f[N],ch[N][2],key[N],sz[N],same[N],rev[N],sum[N],maxl[N],maxr[N],maxx[N];
inline void Clear(int x)
{
    f[x]=ch[x][0]=ch[x][1]=key[x]=sz[x]=rev[x]=sum[x]=maxl[x]=maxr[x]=0;
    same[x]=inf;
    maxx[x]=-inf;
}
inline int get(int x)
{
    return ch[f[x]][1]==x;
}
inline void delp(int x)
{
    q[++tail]=x;
}
int newp()
{
    head++;
    if (ch[q[head]][0]) delp(ch[q[head]][0]);
    if (ch[q[head]][1]) delp(ch[q[head]][1]);
    Clear(q[head]);
    return q[head];
}
void update(int x)
{
    sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
    sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+key[x];
    maxl[x]=max(maxl[ch[x][0]],key[x]+sum[ch[x][0]]+maxl[ch[x][1]]);
    maxr[x]=max(maxr[ch[x][1]],key[x]+sum[ch[x][1]]+maxr[ch[x][0]]);
    maxx[x]=max(maxx[ch[x][0]],maxx[ch[x][1]]);
    maxx[x]=max(maxx[x],maxr[ch[x][0]]+key[x]+maxl[ch[x][1]]);
}
void pushdown(int x)
{
    if (x==0) return;
    if (same[x]!=inf)
    {
        if (ch[x][0])
        {
            int lch=ch[x][0];
            key[lch]=same[x];
            sum[lch]=sz[lch]*same[x];
            if (same[x]>=0)
                maxx[lch]=maxl[lch]=maxr[lch]=sum[lch];
            else
            {
                maxx[lch]=same[x];
                maxl[lch]=maxr[lch]=0;
            }
            same[lch]=same[x];
        }
        if (ch[x][1])
        {
            int rch=ch[x][1];
            key[rch]=same[x];
            sum[rch]=sz[rch]*same[x];
            if (same[x]>=0)
                maxx[rch]=maxl[rch]=maxr[rch]=sum[rch];
            else
            {
                maxx[rch]=same[x];
                maxl[rch]=maxr[rch]=0;
            }
            same[rch]=same[x];
        }
        same[x]=inf;
    }
    if (rev[x])
    {
        if (ch[x][0])
        {
            int now=ch[x][0];
            rev[now]^=1;
            swap(ch[now][0],ch[now][1]);
            swap(maxl[now],maxr[now]);
        }
        if (ch[x][1])
        {
            int now=ch[x][1];
            rev[now]^=1;
            swap(ch[now][0],ch[now][1]);
            swap(maxl[now],maxr[now]);
        }
        rev[x]=0;
    }
}
int build(int l,int r,int fa,int *val)
{
    if (l>r) return 0;
    int mid=(l+r)>>1;
    int now=newp();
    f[now]=fa;key[now]=val[mid];maxx[now]=val[mid];
    int lch=build(l,mid-1,now,val);
    int rch=build(mid+1,r,now,val);
    ch[now][0]=lch;ch[now][1]=rch;
    update(now);
    return now;
}
void Rotate(int x)
{
    pushdown(f[x]);
    pushdown(x);
    int fa=f[x],ff=f[fa],kind=get(x);
    ch[fa][kind]=ch[x][kind^1];f[ch[x][kind^1]]=fa;
    ch[x][kind^1]=fa;f[fa]=x;
    f[x]=ff;
    if (ff)
        ch[ff][ch[ff][1]==fa]=x;
    update(fa);
    update(x);
}
void splay(int x,int y)
{
    for(int fa;(fa=f[x])!=y;Rotate(x))
        if (f[fa]!=y)
            Rotate((get(fa)==get(x))?fa:x);
    if (y==0) root=x;
}
int Find(int x)
{
    int now=root;
    while(1)
    {
        pushdown(now);
        if (ch[now][0]&&sz[ch[now][0]]>=x)
            now=ch[now][0];
        else
        {
            x-=sz[ch[now][0]];
            if (x==1) return now;
            x--;
            now=ch[now][1];
        }
    }
}

void Treaval(int x) {
    if(x) {
        pushdown(x);
        Treaval(ch[x][0]);
        printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,key = %2d sum = %2d maxsum=%2d \n",x,ch[x][0],ch[x][1],f[x],sz[x],key[x],sum[x],maxx[x]);
        Treaval(ch[x][1]);
    }
}
void debug() {printf("%d\n",root);Treaval(root);}

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    a[1]=-inf;a[n+2]=inf;maxx[0]=-inf;
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i+1]);
    for(int i=1;i<=500000;i++)
        delp(i);
    root=build(1,n+2,0,a);
    char s[20];
    int pos,tot,c;
    while(m--)
    {
        scanf("%s",s);
        switch(s[0])
        {
            case 'I':
            {
                scanf("%d%d",&pos,&tot);
                for(int i=1;i<=tot;i++)
                    scanf("%d",&b[i]);
                int now=build(1,tot,0,b);
                int aa=Find(pos+1);
                int bb=Find(pos+2);
                splay(aa,0);
                splay(bb,aa);
                ch[ch[root][1]][0]=now;
                f[now]=ch[root][1];
                update(ch[root][1]);
                update(root);
                //debug();
                break;
            }
            case 'D':
            {
                scanf("%d%d",&pos,&tot);
                int aa=Find(pos);
                int bb=Find(pos+tot+1);
                splay(aa,0);
                splay(bb,aa);
                delp(ch[ch[root][1]][0]);
                ch[ch[root][1]][0]=0;
                update(ch[root][1]);
                update(root);
                //debug();
                break;
            }
            case 'M':
                if (s[2]=='K')
                {
                    scanf("%d%d%d",&pos,&tot,&c);
                    int aa=Find(pos);
                    int bb=Find(pos+tot+1);
                    splay(aa,0);
                    splay(bb,aa);
                    int now=ch[ch[root][1]][0];
                    same[now]=c;
                    key[now]=c;
                    sum[now]=c*sz[now];
                    if (c>=0)
                        maxx[now]=maxl[now]=maxr[now]=sum[now];
                    else
                    {
                        maxx[now]=c;
                        maxl[now]=maxr[now]=0;
                    }
                    update(ch[root][1]);
                    update(root);
                    //debug();
                }
                else
                {
                    int aa=Find(1);
                    int bb=Find(sz[root]);
                    splay(aa,0);
                    splay(bb,aa);
                    printf("%d\n",maxx[ch[ch[root][1]][0]]);
                }
                break;
            case 'R':
            {
                scanf("%d%d",&pos,&tot);
                if (tot==1) break;
                int aa=Find(pos);
                int bb=Find(pos+tot+1);
                splay(aa,0);
                splay(bb,aa);
                int now=ch[ch[root][1]][0];
                rev[now]^=1;
                swap(ch[now][0],ch[now][1]);
                swap(maxl[now],maxr[now]);
                break;
            }
            case 'G':
            {
                scanf("%d%d",&pos,&tot);
                int aa=Find(pos);
                int bb=Find(pos+tot+1);
                splay(aa,0);
                splay(bb,aa);
                //debug();
                printf("%d\n",sum[ch[ch[root][1]][0]]);
                break;
            }
        }
    }
    return 0;
}

  

posted @ 2017-08-22 10:25  BK_201  阅读(162)  评论(0编辑  收藏  举报