就放一個 Splay 平衡樹板子…… 感受總算理解一點了……
破題調了兩天多,最後是用第一天第一遍寫的代碼改了維護一個變量的方法,而後就 A 了……
咱寫的 Splay 有一點缺陷,就是每一個葉子節點下面還掛着兩個不產生貢獻的空節點;不過對漸進複雜度都沒什麼影響,並且能夠防止莫名的 RE。
node
#include <cmath> #include <stack> #include <cstdio> #include <cctype> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define lch child[0] #define rch child[1] const int maxn = 1000000 + 10; int n, m, a[maxn], node_num; char ques[11]; inline int read() { register int ch = 0; register int w = 0, x = 0; for( ; !isdigit(ch); w = w | (ch == '-'), ch = getchar()) ; for( ; isdigit(ch); x = (x * 10) + (ch ^ 48), ch = getchar()) ; return w ? -x : x; } struct Node { int id; int size, val, sum, set, rev, lef_max, rig_max, all_max; Node *child[2], *pre; Node() { size = val = sum = rev = lef_max = rig_max = 0, all_max = -maxn, set = maxn, pre = child[0] = child[1] = NULL; } ~Node() {}; } *p_root, node[maxn], clear; std::stack<Node*> bin; class Splay { public: inline void Maintain(Node *root) { root->size = root->lch->size + root->rch->size + 1; root->sum = root->lch->sum + root->rch->sum + root->val; root->lef_max = max(root->lch->lef_max, root->lch->sum + root->val + root->rch->lef_max); root->rig_max = max(root->rch->rig_max, root->rch->sum + root->val + root->lch->rig_max); root->all_max = max(max(root->lch->all_max, root->rch->all_max), root->lch->rig_max + root->val + root->rch->lef_max); } inline void Pushdown(Node *root) { if( root->rev ) { swap(root->lch->lch, root->lch->rch), swap(root->lch->lef_max, root->lch->rig_max); swap(root->rch->lch, root->rch->rch), swap(root->rch->lef_max, root->rch->rig_max); root->lch->rev = root->lch->rev ^ 1, root->rch->rev = root->rch->rev ^ 1, root->rev = 0; } if( root->set != maxn ) { root->lch->val = root->set, root->lch->sum = root->set * root->lch->size; root->rch->val = root->set, root->rch->sum = root->set * root->rch->size; if( root->set > 0 ) { root->lch->lef_max = root->lch->rig_max = root->lch->all_max = root->lch->size * root->set; root->rch->lef_max = root->rch->rig_max = root->rch->all_max = root->rch->size * root->set; } else { root->lch->lef_max = root->lch->rig_max = 0, root->lch->all_max = root->set; root->rch->lef_max = root->rch->rig_max = 0, root->rch->all_max = root->set; } root->lch->set = root->rch->set = root->set, root->set = maxn; } } inline bool Choosech(Node *root) { return root->pre->rch == root; } inline void Rotate(Node *root) { Node *p = root->pre; bool pos = Choosech(root); Pushdown(p), Pushdown(root), p->child[pos] = root->child[!pos]; if( root->child[!pos] ) root->child[!pos]->pre = p; if( root->pre = p->pre ) root->pre->child[Choosech(p)] = root; p->pre = root, root->child[!pos] = p; Maintain(p), Maintain(root); if( root->pre == NULL ) p_root = root; } inline void Spaly(Node *root, Node *posi) { Node *p = root->pre; while( (p = root->pre) != posi ) { if( p->pre != posi ) Rotate(Choosech(root) == Choosech(p) ? p : root); Rotate(root); } } inline Node* Findnode(Node *root, int k) { int tmp = 0; root = p_root; while( true ) { Pushdown(root); if( root->lch && k <= root->lch->size ) { root = root->lch; continue; } tmp = (root->lch ? root->lch->size : 0) + 1; if( k <= tmp ) return root; k = k - tmp, root = root->rch; } } inline void Build(Node *root, int l, int r) { if( l > r ) return ; int mid = (l + r) >> 1; root->val = root->sum = root->all_max = a[mid], root->lef_max = root->rig_max = max(0, a[mid]), root->size = 1; if( bin.empty() ) root->lch = &node[++node_num]; else root->lch = bin.top(), bin.pop(); root->lch->pre = root, Build(root->lch, l, mid - 1); if( bin.empty() ) root->rch = &node[++node_num]; else root->rch = bin.top(), bin.pop(); root->rch->pre = root, Build(root->rch, mid + 1, r); if( l < r ) Maintain(root); } inline void Retrie(Node *root) { if( root->lch ) Retrie(root->lch); if( root->rch ) Retrie(root->rch); *root = clear, bin.push(root); } inline void Insert(int x, int len) { for(int i = 1; i <= len; ++i) a[i] = read(); Node *p = NULL; p = Findnode(p_root, x), Spaly(p, NULL), p = Findnode(p_root, x + 1), Spaly(p, p_root); Retrie(p->lch), p->lch = bin.top(), bin.pop(); n = n + len, p->lch->pre = p, Build(p->lch, 1, len), Maintain(p), Maintain(p->pre); } inline void Delete(int x, int len) { Node *p = NULL; p = Findnode(p_root, x - 1), Spaly(p, NULL), p = Findnode(p_root, x + len), Spaly(p, p_root); Retrie(p->lch), p->lch = bin.top(), bin.pop(); n = n - len, p->lch->pre = p, Maintain(p), Maintain(p->pre); } inline void Revers(int x, int len) { Node *p = NULL; p = Findnode(p_root, x - 1), Spaly(p, NULL), p = Findnode(p_root, x + len), Spaly(p, p_root); p->lch->rev = p->lch->rev ^ 1; swap(p->lch->lch, p->lch->rch), swap(p->lch->lef_max, p->lch->rig_max); } inline void Getsum(int x, int len) { Node *p = NULL; p = Findnode(p_root, x - 1), Spaly(p, NULL), p = Findnode(p_root, x + len), Spaly(p, p_root); printf("%d\n", p->lch->sum); } inline void Setnum(int x, int len, int c) { Node *p = NULL; p = Findnode(p_root, x - 1), Spaly(p, NULL), p = Findnode(p_root, x + len), Spaly(p, p_root); p->lch->set = c, p->lch->val = p->lch->set, p->lch->sum = len * p->lch->set; if( p->lch->set > 0 ) p->lch->lef_max = p->lch->rig_max = p->lch->all_max = len * p->lch->set; else p->lch->lef_max = p->lch->rig_max = 0, p->lch->all_max = c; } inline void Maxsum() { Node *p = NULL; p = Findnode(p_root, 1), Spaly(p, NULL), p = Findnode(p_root, n), Spaly(p, p_root); printf("%d\n", p->lch->all_max); } } tree; inline void Print(Node *root) { if( root->size > 1 ) tree.Pushdown(root); if( root->lch ) Print(root->lch); if( root->val ) printf("%d ", root->val); if( root->rch ) Print(root->rch); if( root->size > 1 ) tree.Maintain(root); } int main(int argc, char const *argv[]) { scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i) a[i + 1] = read(); p_root = &node[++node_num], tree.Build(p_root, 1, n + 2); n = n + 2; for(int x, len, i = 1; i <= m; ++i) { scanf("%s", ques); switch( ques[0] ^ ques[2] ) { case ('I' ^ 'S' ): x = read() + 1, len = read(), tree.Insert(x, len); break; case ('D' ^ 'L' ): x = read() + 1, len = read(), tree.Delete(x, len); break; case ('R' ^ 'V' ): x = read() + 1, len = read(), tree.Revers(x, len); break; case ('G' ^ 'T' ): x = read() + 1, len = read(), tree.Getsum(x, len); break; case ('M' ^ 'K' ): x = read() + 1, len = read(), tree.Setnum(x, len, read()); break; case ('M' ^ 'X' ): tree.Maxsum(); break; default : break; } // Node *p = NULL; // p = tree.Findnode(p_root, 1), tree.Spaly(p, NULL), p = tree.Findnode(p_root, n), tree.Spaly(p, p_root); // Print(p->lch), printf("\n"); } return 0; }