BZOJ 1500: [NOI2005]维修数列

Description

Input

输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。

第2行包含N个数字,描述初始时的数列。

以下M行,每行一条命令,格式参见问题描述中的表格。

任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。

插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

Output

对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。

Sample Input

9 8

2 -6 3 5 1 -5 -3 6 3

GET-SUM 5 4

MAX-SUM

INSERT 8 3 -5 7 2

DELETE 12 1

MAKE-SAME 3 3 2

REVERSE 3 6

GET-SUM 5 4

MAX-SUM

Sample Output

-1

10

1

10

HINT

Solution

平衡树

Splay裸题。每段区间维护最大前缀和,最大后缀和,最大子串和。

Code

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 600055;
char str[15];
int n, m, A[N], siz[N], sum[N], suf[N], ans[N], pre[N], c[N][2], val[N], sta[N], fa[N], root, tail;
bool rev[N], laz[N];
inline int getint() {
    int r = 0, k = 1; char c = getchar();
    for (; c < '0' || c > '9'; c = getchar()) if (c == '-') k = -1;
    for (; '0' <= c && c <= '9'; c = getchar()) r = r * 10 - '0' + c;
    return r * k;
}
inline void pu(int x) {
    int lc = c[x][0], rc = c[x][1], L = max(0, suf[lc]), R = max(0, pre[rc]);
    siz[x] = 1 + siz[lc] + siz[rc];
    sum[x] = val[x] + sum[lc] + sum[rc];
    pre[x] = max(pre[lc], sum[lc] + val[x] + R);
    suf[x] = max(suf[rc], sum[rc] + val[x] + L);
    ans[x] = max(L + val[x] + R, max(ans[lc], ans[rc]));
}
inline void ReverseNode(int x) {
	if (x) {
	    rev[x] = !rev[x];
	    swap(pre[x], suf[x]);
	    swap(c[x][0], c[x][1]);
	}
}
inline void FillNode(int x, int v) {
	if (x) {
	    sum[x] = v * siz[x];
		val[x] = v;
		laz[x] = true;
	    pre[x] = suf[x] = ans[x] = max(v, sum[x]);
	}
}
inline void pd(int x) {
    int &lc = c[x][0], &rc = c[x][1];
    if (laz[x]) {
        FillNode(lc, val[x]);
        FillNode(rc, val[x]);
        laz[x] = false;
    }
    if (rev[x]) {
        ReverseNode(lc);
        ReverseNode(rc);
        rev[x] = false;
    }
}
inline void rotate(int x) {
    int y = fa[x], z = fa[y], a = (c[y][1] == x), b = a^1;
    if (z) c[z][c[z][1] == y] = x;
    fa[x] = z; fa[y] = x; if (c[x][b]) fa[c[x][b]] = y;
    c[y][a] = c[x][b]; c[x][b] = y;
    pu(y); pu(x);
}
inline void Splay(int x, int pos = 0) {
    while (fa[x] != pos) {
        int y = fa[x], z = fa[y];
        if (z != pos) {
            if (c[y][0] == x ^ c[z][0] == y) rotate(x);
            else rotate(y);
        }
        rotate(x);
    }
    if (pos == 0) root = x;
}
int Kth(int x, int K) {
    pd(x);
    int lc = c[x][0], lsiz = siz[lc];
    if (K == lsiz + 1) return x;
    if (K <= lsiz) return Kth(lc, K);
    return Kth(c[x][1], K - lsiz - 1);
}
int Build(int l, int r) {
    if (l > r) return 0;
    int ret = sta[tail--], mid = (l + r) >> 1;
    val[ret] = A[mid];
    if (c[ret][0] = Build(l, mid-1)) fa[c[ret][0]] = ret;
    if (c[ret][1] = Build(mid+1, r)) fa[c[ret][1]] = ret;
    pu(ret); return ret;
}
inline void Insert(int p, int cnt) {
    for (int i = 1; i <= cnt; ++i) A[i] = getint();
    int p1 = Kth(root, p+1);
    Splay(p1);
    int p2 = Kth(root, p+2);
    Splay(p2, p1);
    c[p2][0] = Build(1, cnt);
    fa[c[p2][0]] = p2;
    pu(p2); pu(p1);
}
void DeleteTree(int &x) {
    if (x == 0) return;
    fa[x] = laz[x] = rev[x] = 0;
    DeleteTree(c[x][0]);
    DeleteTree(c[x][1]);
    sta[++tail] = x;
    x = 0;
}
inline void Delete(int p, int cnt) {
    int p1 = Kth(root, p);
    Splay(p1);
    int p2 = Kth(root, p+cnt+1);
    Splay(p2, p1);
    DeleteTree(c[p2][0]);
    pu(p2); pu(p1);
}
inline void MakeSame(int p, int cnt, int v) {
    int p1 = Kth(root, p);
    Splay(p1);
    int p2 = Kth(root, p+cnt+1);
    Splay(p2, p1);
    FillNode(c[p2][0], v);
    pu(p2); pu(p1);
}
inline void Reverse(int p, int cnt) {
    int p1 = Kth(root, p);
    Splay(p1);
    int p2 = Kth(root, p+cnt+1);
    Splay(p2, p1);
    ReverseNode(c[p2][0]);
    pu(p2); pu(p1);
}
inline int GetSum(int p, int cnt) {
    int p1 = Kth(root, p);
    Splay(p1);
    int p2 = Kth(root, p+cnt+1);
    Splay(p2, p1);
    return sum[c[p2][0]];
}
int main() {
    for (int i = 1; i <= 555555; ++i) sta[i] = 555556-i;
    tail = 555555;
    int x, y;
    n = getint(); m = getint();
    ans[0] = A[0] = A[1] = -1009999999;
    root = Build(0, 1);
    Insert(0, n);
    while (m--) {
        scanf("%s", str);
        if (str[0] == 'I') {
            x = getint(); y = getint();
            Insert(x, y);
        } else if (str[0] == 'D') {
            x = getint(); y = getint();
            Delete(x, y);
        } else if (str[0] == 'R') {
            x = getint(); y = getint();
            Reverse(x, y);
        } else if (str[0] == 'G') {
            x = getint(); y = getint();
            printf("%d\n", GetSum(x, y));
        } else if (str[2] == 'K') {
            x = getint(); y = getint();
            MakeSame(x, y, getint());
        } else if (str[2] == 'X') {
            printf("%d\n", ans[root]);
        }
    }
}