这道题还是比较裸的, 就是有点难码, 感觉能错的地方都错了一遍... 这里就提一些注意事项吧:
感觉对Splay一些基本操作的理解不够,或者说,对于线段树的一些基本操作理解不够.在维护下传标记方面Splay和线段树是相通的.这是一些问题:
- 标记在什么时候下传:更具定义,在需要往下走的时候下传,即寻找第k大的时候.其他时候…其实是没有必要的.
- 修改标记的定义:和线段树一样,一个点的标记定义为它的子树应该要更改的部分,所以在修改一个值的同时,不仅要修改它的标记,还要将它本身的值修改.这东西最好写一个函数,至少在这道题写函数之后才对的,并且并不知道bug处在哪
- Splay前的更新:即在Splay之前将根节点到这个点上的所有点都pushdown.虽然有些代码没有写,但感觉还是要写一写为好.不写可能会错?
- 前缀,后缀最大值的包含与不包含的问题:考虑它能不能不选.例如这道题,不能不选,所以如果全是负数,最大值也不能是0.
- 前,后哨兵问题:哨兵是肯定要有的,否则肯定会出bug.对于哨兵的值的问题…这种维护数列的问题一般是设成0吧…这样的话就不会影响原来的值了.如果会影响的话,那么对于输出值的问题就可以将整个区间split出来就好了.
这里贴上调了若干天的代码 >_< :
#include <bits/stdc++.h>
#define lc(x) ch[(x)][0]
#define rc(x) ch[(x)][1]
#define INF 0x3f3f3f3f
#define N 1000006
using namespace std;
inline void cmax(int& x, int y) {
if (x < y) x = y;
}
inline int read() { int x; scanf("%d", &x); return x;}
int cnt = 0, root, fa[N], ch[N][2], val[N], sz[N], rpl[N], rev[N], sum[N], lft[N], rht[N], mxs[N];
int stk[N], top;
inline void update(int x) {
sz[x] = sz[lc(x)] + sz[rc(x)] + 1;
sum[x] = sum[lc(x)] + sum[rc(x)] + val[x];
lft[x] = sum[lc(x)] + val[x];
if (rc(x)) cmax(lft[x], lft[x] + lft[rc(x)]);
if (lc(x)) cmax(lft[x], lft[lc(x)]);
rht[x] = sum[rc(x)] + val[x];
if (lc(x)) cmax(rht[x], rht[x] + rht[lc(x)]);
if (rc(x)) cmax(rht[x], rht[rc(x)]);
mxs[x] = max(0, rht[lc(x)]) + val[x] + max(0, lft[rc(x)]);
if (lc(x)) cmax(mxs[x], mxs[lc(x)]);
if (rc(x)) cmax(mxs[x], mxs[rc(x)]);
}
inline void rever(int x) {
swap(lc(x), rc(x));
swap(lft[x], rht[x]);
rev[x] ^= 1;
}
inline void tagup(int x, int w) {
rpl[x] = val[x] = w;
sum[x] = lft[x] = rht[x] = mxs[x] = sz[x] * w;
if (w < 0) lft[x] = rht[x] = mxs[x] = w;
}
inline void pushdown(int x) {
if (rev[x]) {
if (lc(x)) rever(lc(x));
if (rc(x)) rever(rc(x));
rev[x] = 0;
}
if (rpl[x] != INF) {
if (lc(x)) tagup(lc(x), rpl[x]);
if (rc(x)) tagup(rc(x), rpl[x]);
rpl[x] = INF;
}
}
void pushup(int x) {
if (fa[x]) pushup(fa[x]);
pushdown(x);
}
inline void rotate(int x) {
int y = fa[x], z = fa[y], d = rc(y) == x;
pushdown(y), pushdown(x);
ch[y][d] = ch[x][!d], fa[ch[y][d]] = y;
fa[y] = x, ch[x][!d] = y; fa[x] = z;
if (z) ch[z][rc(z) == y] = x;
update(y), update(x);
}
inline void splay(int x, int goal) {
pushup(x);
while (fa[x] != goal) {
int y = fa[x], z = fa[y];
if (z != goal) rotate((rc(y) == x) == (rc(z) == y) ? y : x);
rotate(x);
}
if (!goal) root = x;
}
inline int Get() {
return top ? stk[top--] : ++cnt;
}
int kth(int k) {
int rt = root;
while (rt) {
pushdown(rt);
if (sz[lc(rt)] >= k) rt = lc(rt);
else if (sz[lc(rt)] + 1 == k) return rt;
else k -= sz[lc(rt)] + 1, rt = rc(rt);
}
}
inline void isrt() {
int k = read(), tot = read();
splay(kth(k + 2), 0), splay(kth(k + 1), root);
int lst = lc(root);
rc(lst) = Get();
while (tot--) {
fa[rc(lst)] = lst;
lst = rc(lst);
val[lst] = read();
if (tot) rc(lst) = Get();
}
splay(lst, 0);
}
void recy(int rt) {
if (lc(rt)) recy(lc(rt));
if (rc(rt)) recy(rc(rt));
sum[rt] = val[rt] = sz[rt] = lc(rt) = rc(rt) = fa[rt] = 0;
rpl[rt] = INF, rev[rt] = lft[rt] = rht[rt] = mxs[rt] = 0;
stk[++top] = rt;
}
void output(int x) {
pushdown(x);
if (lc(x)) output(lc(x));
if (rc(x)) output(rc(x));
update(x);
}
inline void dele() {
int k = read(), tot = read(), x;
splay(kth(k + tot + 1), 0), splay(kth(k), root);
x = rc(lc(root));
recy(x); rc(lc(root)) = 0;
splay(lc(root), 0);
}
inline void mdfy() {
int k = read(), tot = read(), c = read(), x;
splay(kth(k + tot + 1), 0), splay(kth(k), root);
x = rc(lc(root));
tagup(x, c);
splay(x, 0);
}
inline void reve() {
int k = read(), tot = read(), x, y = kth(k), z = kth(k + tot + 1);
splay(z, 0), splay(y, root);
x = rc(lc(root));
rever(x);
splay(x, 0);
}
inline int gtsum() {
int k = read(), tot = read(), x, y = kth(k), z = kth(k + tot + 1);
splay(z, 0), splay(y, root);
x = rc(lc(root));
return sum[x];
}
void getupdate(int x) {
pushdown(x);
if (lc(x)) getupdate(lc(x));
if (rc(x)) getupdate(rc(x));
update(x);
}
inline int mxsum() {
splay(1, 0), splay(kth(sz[root]), 1);
return mxs[lc(rc(root))];
}
int main() {
memset(rpl, 0x3f, sizeof rpl);
int n, m;
n = read(), m = read();
root = 1;
rc(1) = 2;
for (int i = 2; i <= n + 1; ++i) {
val[i] = read();
fa[i] = i - 1;
rc(i) = i + 1;
update(i);
}
fa[cnt = n + 2] = n + 1;
splay(n + 2, root);
getupdate(root);
char op[20];
while (m--) {
scanf("%s", op);
if (*op == 'I') isrt();
if (*op == 'D') dele();
if (*op == 'M' && *(op + 2) == 'K') mdfy();
if (*op == 'R') reve();
if (*op == 'G') printf("%d
", gtsum());
if (*op == 'M' && *(op + 2) == 'X') printf("%d
", mxsum());
}
return 0;
}