[BZOJ1500][NOI2005][Splay]维修数列

[Problem Description]

[Data Structure]
Splay
[Analysis]
Splay没话说,维护节点信息和pushdown,update与线段树有些像。
[Pay Attention]
这里有一个逗比的地方,MAX-SUM不包括空串这种情况,也就是说,就算序列里面最大的数是负数,也不能输出0,而是输出那个负数。
[Code]
/**************************************************************
    Problem: 1500
    User: gaotianyu1350
    Language: C++
    Result: Accepted
    Time:4456 ms
    Memory:42352 kb
****************************************************************/
 
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
#include <iostream>
using namespace std;
 
#define MAXN 700000
 
queue<int> pool;
struct splayNode
{
    int ch[2];
    int f;
    int key, size, sum, lmax, rmax, mmax, doubi;
    int flagSame, flagRe, nSame;
    splayNode()
    {
        f = ch[0] = ch[1] = key = size = sum = lmax = rmax = mmax = 0;
        flagSame = flagRe = nSame = 0;
        doubi = 0;
    }
    void newNode(int father, int value)
    {
        f = father;
        ch[0] = ch[1] = 0;
        key = sum = value;
        lmax = rmax = mmax = max(value, 0);
        doubi = value;
        size = 1;
        flagSame = flagRe = nSame = 0;
    }
    void delNode()
    {
        f = 0;
        ch[0] = ch[1] = key = size = sum = lmax = rmax = mmax = 0;
        flagSame = flagRe = nSame = 0;
        doubi = 0;
    }
}s[MAXN];
int root;
int temp[MAXN], cnt;
 
inline void init()
{
    while (!pool.empty()) pool.pop();
    for (int i = 1; i < MAXN; i++)
        pool.push(i);
    root = 0;
}
 
inline int newNode(int father, int key)
{
    int now = pool.front(); pool.pop();
    s[now].newNode(father, key);
    //if (father) s[father].ch[which] = now;
    return now;
}
 
inline void delTree(int now)
{
    queue<int> q;
    while (!q.empty()) q.pop();
    q.push(now);
    while (!q.empty())
    {
        int now = q.front(); q.pop();
        if (s[now].ch[0]) q.push(s[now].ch[0]);
        if (s[now].ch[1]) q.push(s[now].ch[1]);
        s[now].delNode();
        pool.push(now);
    }
}
 
inline void update(int now)
{
    int left = s[now].ch[0], right = s[now].ch[1];
    s[now].size = s[left].size + s[right].size + 1;
    s[now].sum = s[left].sum + s[right].sum + s[now].key;
    s[now].lmax = max(s[left].lmax, s[left].sum + s[now].key + s[right].lmax);
    s[now].rmax = max(s[right].rmax, s[right].sum + s[now].key + s[left].rmax);    
    s[now].mmax = max(max(s[left].mmax, s[right].mmax), s[left].rmax + s[now].key + s[right].lmax);   
    s[now].doubi = s[now].key;
    if (left) s[now].doubi = max(s[now].doubi, s[left].doubi);
    if (right) s[now].doubi = max(s[now].doubi, s[right].doubi);
}
 
inline void Reverse(int now)
{
    int temp = s[now].ch[0];
    s[now].ch[0] = s[now].ch[1];
    s[now].ch[1] = temp;
    s[now].flagRe ^= 1;
    temp = s[now].lmax;
    s[now].lmax = s[now].rmax;
    s[now].rmax = temp;
}
 
inline void Same(int now, int value)
{
    s[now].key = s[now].nSame = value;
    s[now].flagSame = 1;
    s[now].sum = s[now].size * s[now].key;
    s[now].lmax = s[now].rmax = s[now].mmax = s[now].sum > 0 ? s[now].sum : 0;
    s[now].doubi = value;
}
 
inline void pushdown(int now)
{
    int left = s[now].ch[0], right = s[now].ch[1];
    if (s[now].flagSame)
    {
        if (left) Same(left, s[now].nSame);
        if (right) Same(right, s[now].nSame);
        s[now].flagSame = 0;
        s[now].nSame = 0;
    }
    if (s[now].flagRe)
    {
        if (left) Reverse(left); 
        if (right) Reverse(right);
        s[now].flagRe = 0;
    }
}
 
inline int get(int now)
{
    int father = s[now].f;
    return now == s[father].ch[0] ? 0 : 1;
}
 
inline void rotate(int now)
{
    int father = s[now].f, oldfather = s[father].f, which = get(now);
    pushdown(father);
    pushdown(now);
    s[father].ch[which] = s[now].ch[which ^ 1];
    s[s[father].ch[which]].f = father;
    s[now].ch[which ^ 1] = father;
    s[father].f = now;
    s[now].f = oldfather;
    if (oldfather)
        s[oldfather].ch[s[oldfather].ch[0] == father ? 0 : 1] = now;
    update(father);
    update(now);
    //if (oldfather) update(oldfather);
}
 
inline void splay(int now, int tar)
{
    for (int father = s[now].f; father != tar; rotate(now), father = s[now].f)
        if (s[father].f != tar)
            get(now) == get(father) ? rotate(father) : rotate(now);
    if (tar == 0)
        root = now;
}
 
inline int find(int location)
{
    int now = root;
    while (now)
    {
        pushdown(now);
        if (location == s[s[now].ch[0]].size + 1)
            return now;
        if (location <= s[s[now].ch[0]].size)
            now = s[now].ch[0];
        else
            location -= s[s[now].ch[0]].size + 1, now = s[now].ch[1];
    }
    return -1000000000;
}
 
inline int build(int father, int left, int right)
{
    if (left > right) return 0;
    int mid = (left + right) >> 1;
    int now = newNode(father, temp[mid]);
    s[now].ch[0] = build(now, left, mid - 1);
    s[now].ch[1] = build(now, mid + 1, right);
    update(now);
    return now;
}
 
inline void add(int pos)
{
    int nleft = find(pos), nright = find(pos + 1);
    splay(nleft, 0);
    splay(nright, root);
    if (s[nright].ch[0]) printf("Wrong at 186\n");
    s[nright].ch[0] = build(nright, 1, cnt);
    update(nright);update(root);
}
 
inline void del(int pos, int tot)
{
    int nleft = find(pos - 1), nright = find(pos + tot);
    splay(nleft, 0);
    splay(nright, root);
    if (!s[nright].ch[0]) printf("Wrong at 190\n");
    else
    {
        delTree(s[nright].ch[0]);
        s[nright].ch[0] = 0;
        update(nright);update(root);
    }
}
 
inline void makesame(int pos, int tot, int value)
{
    int nleft = find(pos - 1), nright = find(pos + tot);
    splay(nleft, 0);
    splay(nright, root);
    if (!s[nright].ch[0]) printf("Wrong at 203\n");
    else
    {
        int now = s[nright].ch[0];
        Same(now, value);
        update(nright);update(root);
    }
}
 
inline void makereverse(int pos, int tot)
{
    int nleft = find(pos - 1), nright = find(pos + tot);
    splay(nleft, 0);
    splay(nright, root);
    if (!s[nright].ch[0]) printf("Wrong at 218\n");
    else
    {
        int now = s[nright].ch[0];
        Reverse(now);
        update(nright);update(root);
    }
}
 
inline int getSum(int pos, int tot)
{
    int nleft = find(pos - 1), nright = find(pos + tot);
    if (tot == 0) return 0;
    splay(nleft, 0);
    splay(nright, root);
    if (!s[nright].ch[0]) {printf("Wrong at 232\n");return -233;}
    else
    {
        int now = s[nright].ch[0];
        return s[now].sum;
    }
}
 
inline int getMax()
{
 
    if (s[root].doubi <= 0)
        return s[root].doubi;
    else
        return s[root].mmax;
}
 
inline int quickread()
{
    int ans = 0;
    char c;
    bool fu = false;
    c = getchar();
    while (!(('0' <= c && c <= '9') || c == '-'))
        c = getchar();
    if (c == '-')
    {
        fu = true;
        c = getchar();
    }
    while ('0' <= c && c <= '9')
    {
        ans = ans * 10 + c - '0';
        c = getchar();
    }
    return fu ? - ans : ans;
}
 
int main()
{
    //freopen("input2.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    init();
    temp[1] = temp[2] = -1000000000;
    root = build(0, 1, 2);
    int m;
    char order[15];
    cnt = quickread();
    m = quickread();
    for (int i = 1; i <= cnt; i++)
        temp[i] = quickread();
    add(1);
    while (m--)
    {
        scanf(" %s", order);
        int pos, value;
        switch (order[0])
        {
            case 'I':
                int pos;
                pos = quickread();
                cnt = quickread();
                for (int i = 1; i <= cnt; i++)
                    temp[i] = quickread();
                add(pos + 1);
                break;
            case 'D':
                pos = quickread();
                cnt = quickread();
                del(pos + 1, cnt);
                break;
            case 'M':
                if (order[2] == 'K')
                {
                    pos = quickread();
                    cnt = quickread();
                    value = quickread();
                    makesame(pos + 1, cnt, value);
                    break;
                }
                else
                {
                    printf("%d\n", getMax());
                    break;
                }
            case 'R':
                pos = quickread();
                cnt = quickread();
                makereverse(pos + 1, cnt);
                break;
            case 'G':
                pos = quickread();
                cnt = quickread();
                printf("%d\n", getSum(pos + 1, cnt));
                break;
        }
    }
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值