【NOI2005】【splay】维护数列

5 篇文章 0 订阅

这题貌似比operation还要恶心一点。。。

为了练习splay硬着头皮写的虽然现在AC了但我还是完全没有信心能够在考场上写出来,细节太多下面进入正题

1、最大序列和的询问,仿照线段树,需要维护Max,Maxl,Maxr,sum这几个量,在上传的时候更新。

2、由于内存限制,需要回收内存的操作,就是将下标回收进入一个数组,具体见代码

3、标记要向下传递两层(Ps:这个我也不知道为什么,我在这里卡了很久)

4、两个虚拟节点以及Max的初始值为-inf

5、不要将lazy标记与lazy标记的值合并,多开一个bool来标记

这道题的trick暂时就想到这些,至于其他的操作就与一般的splay维护数列的题无异了。

代码

#include<cstdio>
#include<algorithm>
#include<cstring>
#define keyTree ch[ ch[root][1] ][0]
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 550000 + 10;
const int bh = maxn - 10;
struct SplayTree
{
    int ch[maxn][2],pre[maxn],num[maxn];
    int ss[maxn],que[maxn];
    int val[maxn],sum[maxn],sz[maxn];
    int Maxl[maxn],Maxr[maxn],Max[maxn];
    int lazy[maxn];
    bool reserve[maxn],same[maxn];
    int root,top1,top2;
    int max(int a,int b)
    {
        return a > b ? a : b;
    }
    int max(int a,int b,int c)
    {
        return max(max(a,b),c);
    }
    void swap(int &a,int &b)
    {
        int t = a;a = b;b = t;
    }
    void push_up(int x)
    {
        sz[x] = sz[ ch[x][0] ] + sz[ ch[x][1] ] + 1;
        sum[x] = val[x] + sum[ ch[x][0] ] + sum[ ch[x][1] ];
        Maxl[x] = max(Maxl[ ch[x][0] ],sum[ ch[x][0] ] + val[x] + max(0,Maxl[ ch[x][1] ]));
        Maxr[x] = max(Maxr[ ch[x][1] ],sum[ ch[x][1] ] + val[x] + max(0,Maxr[ ch[x][0] ]));
        Max[x] = max(Max[ ch[x][0] ],Max[ ch[x][1] ],val[x]);
        Max[x] = max(Max[x],max(Maxr[ ch[x][0] ],Maxl[ ch[x][1] ]) + val[x]);
        Max[x] = max(Max[x],Maxr[ ch[x][0] ] + val[x] + Maxl[ ch[x][1] ]);
    }
	void deal1(int x,int tmp)
	{
		same[x] = true,lazy[x] = tmp;
		sum[x] = tmp * sz[x];
		Max[x] = Maxl[x] = Maxr[x] = max(sum[x],tmp);
	}
    void deal2(int x)
    {
        reserve[x] = !reserve[x];
        swap(Maxl[x],Maxr[x]);
    }
    void push_down(int x)
    {
        if(same[x])
        {
			val[x] = lazy[x];
			if(ch[x][0])deal1(ch[x][0],lazy[x]);
			if(ch[x][1])deal1(ch[x][1],lazy[x]);
			same[x] = reserve[x] = false;
        }
        if(reserve[x])
        {
            swap(ch[x][0],ch[x][1]);
            swap(Maxl[x],Maxr[x]);
            if(ch[x][0])deal2(ch[x][0]);
            if(ch[x][1])deal2(ch[x][1]);
            reserve[x] = false;
        }
    }
    void Rotate(int x,int f)
    {
        int y = pre[x];
        push_down(y);push_down(x);
        ch[y][!f] = ch[x][f];
        pre[ ch[x][f] ] = y;
        pre[x] = pre[y];
        if(pre[x])ch[ pre[y] ][ ch[pre[y]][1] == y ] = x;
        ch[x][f] = y;
        pre[y] = x;
        push_up(y);
    }
    void Splay(int x,int goal)
    {
        push_down(x);
        while(pre[x] != goal)
        {
            if(pre[pre[x]] == goal)Rotate(x, ch[pre[x]][0] == x);
            else
            {
                int y = pre[x],z = pre[y];
                int f = (ch[z][0] == y);
                if(ch[y][f] == x)Rotate(x,!f),Rotate(x,f);
                else Rotate(y,f),Rotate(x,f);
            }
        }
        push_up(x);
        if(goal == 0)root = x;
    }
    void RotateTo(int k,int goal)
    {
        int x = root;
        push_down(x);
        while(sz[ ch[x][0] ] != k)
        {
            if(k < sz[ ch[x][0] ])x = ch[x][0];
            else
            {
                k -= (sz[ ch[x][0] ] + 1);
                x = ch[x][1];
            }
            push_down(x);
        }
        Splay(x,goal);
    }
    void Newnode(int &x,int c)
    {
        if(top2)x = ss[--top2];
        else x = ++top1;
        ch[x][0] = ch[x][1] = pre[x] = 0;
        sz[x] = 1;
        lazy[x] = 0;
        reserve[x] = same[x] = false;
        val[x] = sum[x] = c;
        Maxl[x] = Maxr[x] = Max[x] = c;
    }
    void makeTree(int &x,int l,int r,int f,int *p)
    {
        if(l > r)return;
        int m = (l + r) >> 1;
        Newnode(x,p[m]);
        makeTree(ch[x][0],l , m - 1,x,p);
        makeTree(ch[x][1],m + 1 , r,x,p);
        pre[x] = f;
        push_up(x);
    }
    void erase(int x)
    {
        int father = pre[x];
        int head = 0,tail = 0;
        for(que[tail++] = x;head < tail;head ++)
        {
            ss[top2++] = que[head];
            if(ch[ que[head] ][0])que[tail++] = ch[ que[head] ][0];
            if(ch[ que[head] ][1])que[tail++] = ch[ que[head] ][1];
        }
        ch[ father ][ ch[father][1] == x ] = 0;
        push_up(father); 
    }
    void init(int n)
    {
		memset(Max,~0x3f,sizeof(Max));
        ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0;
        root = top1 = top2 = 0;
        Newnode(root,-inf);
        Newnode(ch[root][1],-inf);
        pre[ch[root][1]] = root;
        sz[root] = 2;
        for(int i = 1;i <= n;i++)scanf("%d",&num[i]);
        makeTree(keyTree,1,n,ch[root][1],num);
        push_up(ch[root][1]);
        push_up(root);
    }
    void ins(int pos,int tot,int *tmp)
    {
        RotateTo(pos,0);RotateTo(pos + 1,root);
        makeTree(keyTree,1,tot,ch[root][1],tmp);
        Splay(keyTree,0);
    }
    void update(int pos,int tot,int c)
    {
        RotateTo(pos - 1,0);RotateTo(pos + tot,root);
		deal1(keyTree,c);
        Splay(keyTree,0);
    }
    void del(int pos,int tot)
    {
        RotateTo(pos - 1,0);RotateTo(pos + tot,root);
        erase(keyTree);
        Splay(ch[root][1],0);
    }
    void res(int pos,int tot)
    {
        RotateTo(pos - 1,0);RotateTo(pos + tot,root);
        reserve[ keyTree ] = !reserve[ keyTree ];
        Splay(keyTree,0);
    }
    int getsum(int pos,int tot)
    {
        RotateTo(pos - 1,0);RotateTo(pos + tot,root);
        return sum[ keyTree ];
    }
    int query(){return Max[root];}
}Spt;
int n,m;
int tmp[maxn];
void init()
{
    freopen("bzoj1500.in","r",stdin);
    freopen("bzoj1500.out","w",stdout);
}
   
void readdata()
{
    scanf("%d%d",&n,&m);
    Spt.init(n);
    for(int i = 1;i <= m;i++)
    {
        char op[10];
        int pos,tot;
        scanf("%s",op);
        if(!strcmp(op,"MAX-SUM"))printf("%d\n",Spt.query());
        else
        {
            scanf("%d%d",&pos,&tot);
            if(!strcmp(op,"INSERT"))
            {
                for(int j = 1;j <= tot;j++)scanf("%d",&tmp[j]);       
                Spt.ins(pos,tot,tmp);
            }
            if(!strcmp(op,"DELETE"))Spt.del(pos,tot);
            if(!strcmp(op,"MAKE-SAME"))
            {
                int c;
                scanf("%d",&c);
                Spt.update(pos,tot,c);
            }
            if(!strcmp(op,"REVERSE"))Spt.res(pos,tot);
            if(!strcmp(op,"GET-SUM"))printf("%d\n",Spt.getsum(pos,tot));
        }
    }
}
   
int main()
{
    init();
    readdata();
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值