_bzoj1500 [NOI2005]维修数列【真·Splay】
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1500
注意MAX-SUM的时候,不可以是空串。
#include <cstdio> #include <algorithm> const int maxn = 500005; int n, m, top, a[maxn], posi, tot, cc; char opr[15]; struct Node { Node * ch[2]; Node * fa; int key, sm, mxl, mxr, mxs, siz, c, mx; char rev; Node(void); int getsm(void) { return c == -666666? sm: c * siz; } int getmxl(void) { if (c == -666666) { return rev? mxr: mxl; } if (c > 0) { return c * siz; } return 0; } int getmxr(void) { if (c == -666666) { return rev? mxl: mxr; } if (c > 0) { return c * siz; } return 0; } int getmxs(void) { if (c == -666666) { return mxs; } if (c > 0) { return c * siz; } return 0; } int getmx(void) { return c == -666666? mx: c; } } *nil, *root, *tnode; Node * stk[maxn]; Node::Node(void) { ch[0] = ch[1] = fa = nil; key = sm = mxl = mxr = mxs = siz = rev = 0; mx = c = -666666; } inline void pushup(Node * x) { x->siz = x->ch[0]->siz + x->ch[1]->siz + 1; x->sm = x->ch[0]->getsm() + x->ch[1]->getsm() + x->key; x->mxl = std::max(x->ch[0]->getmxl(), x->ch[0]->getsm() + x->key + x->ch[1]->getmxl()); x->mxr = std::max(x->ch[1]->getmxr(), x->ch[1]->getsm() + x->key + x->ch[0]->getmxr()); x->mxs = std::max(x->ch[0]->getmxs(), x->ch[1]->getmxs()); x->mxs = std::max(x->mxs, x->ch[0]->getmxr() + x->key + x->ch[1]->getmxl()); x->mx = std::max(x->ch[0]->getmx(), x->ch[1]->getmx()); x->mx = std::max(x->mx, x->key); } inline void pushdown(Node * x) { if (x->c != -666666) { x->ch[0]->c = x->ch[1]->c = x->c; x->key = x->c; x->sm = x->c * x->siz; if (x->c > 0) { x->mxl = x->mxr = x->mxs = x->sm; } else { x->mxl = x->mxr = x->mxs = 0; } x->c = -666666; } if (x->rev) { x->rev = 0; x->ch[0]->rev ^= 1; x->ch[1]->rev ^= 1; std::swap(x->ch[0], x->ch[1]); } } inline void rotate(Node* x) { Node *y = x->fa; if (y == y->fa->ch[0]) { y->fa->ch[0] = x; } else { y->fa->ch[1] = x; } x->fa = y->fa; int dir = x == y->ch[1]; y->ch[dir] = x->ch[dir ^ 1]; x->ch[dir ^ 1]->fa = y; x->ch[dir ^ 1] = y; y->fa = x; pushup(y); pushup(x); } inline void splay(Node * x, Node * rt) { Node * p; char flag1, flag2; top = 0; for (Node * i = x; i != rt; i = i->fa) { stk[top++] = i; } for (int i = top - 1; ~i; --i) { pushdown(stk[i]); } while (x->fa != rt) { p = x->fa; if (p->fa == rt) { rotate(x); } else { flag1 = p == p->fa->ch[1]; flag2 = x == p->ch[1]; if (flag1 ^ flag2) { rotate(x); } else { rotate(p); } rotate(x); } } if (rt == nil) { root = x; } } inline void modify(int pos1, int pos2) { Node * x = root; pushdown(x); while (pos1 != x->ch[0]->siz + 1) { if (pos1 <= x->ch[0]->siz) { x = x->ch[0]; } else { pos1 -= x->ch[0]->siz + 1; x = x->ch[1]; } pushdown(x); } splay(x, nil); x = root; pushdown(x); while (pos2 != x->ch[0]->siz + 1) { if (pos2 <= x->ch[0]->siz) { x = x->ch[0]; } else { pos2 -= x->ch[0]->siz + 1; x = x->ch[1]; } pushdown(x); } splay(x, root); } inline Node* ist(int left, int right) { if (left > right) { return nil; } Node * rt = new Node, *t; int mid = (left + right) >> 1; rt->key = a[mid]; t = ist(left, mid - 1); t->fa = rt; rt->ch[0] = t; t = ist(mid + 1, right); t->fa = rt; rt->ch[1] = t; pushup(rt); return rt; } void clear(Node * x) { if (x == nil) { return; } clear(x->ch[0]); clear(x->ch[1]); delete x; } int main(void) { //freopen("in.txt", "r", stdin); nil = new Node; root = nil; scanf("%d%d", &n, &m); for (int i = 2; i <= n + 1; ++i) { scanf("%d", a + i); } root = ist(1, n = n + 2); while (m--) { scanf("%s", opr); if (opr[2] == 'S') { // INSERT scanf("%d%d", &posi, &tot); n += tot; ++posi; modify(posi, posi + 1); for (int i = 1; i <= tot; ++i) { scanf("%d", a + i); } tnode = ist(1, tot); tnode->fa = root->ch[1]; root->ch[1]->ch[0] = tnode; pushup(root->ch[1]); pushup(root); } else if (opr[2] == 'L') { // DELETE scanf("%d%d", &posi, &tot); n -= tot; ++posi; modify(posi - 1, posi + tot); clear(root->ch[1]->ch[0]); root->ch[1]->ch[0] = nil; pushup(root->ch[1]); pushup(root); } else if (opr[2] == 'K') { // MAKE-SAME scanf("%d%d%d", &posi, &tot, &cc); ++posi; modify(posi - 1, posi + tot); root->ch[1]->ch[0]->c = cc; pushup(root->ch[1]); pushup(root); } else if (opr[2] == 'V') { // REVERSE scanf("%d%d", &posi, &tot); ++posi; modify(posi - 1, posi + tot); root->ch[1]->ch[0]->rev ^= 1; pushup(root->ch[1]); pushup(root); } else if (opr[2] == 'T') { // GET-SUM scanf("%d%d", &posi, &tot); ++posi; modify(posi - 1, posi + tot); printf("%d\n", root->ch[1]->ch[0]->getsm()); } else { // MAX-SUM modify(1, n); printf("%d\n", root->ch[1]->ch[0]->getmx() > 0? root->getmxs(): root->ch[1]->ch[0]->getmx()); } } return 0; }