[NOI2005]维护数列
就放一个 Splay 平衡树板子…… 感觉总算理解一点了……
破题调了两天多,最后是用第一天第一遍写的代码改了维护一个变量的方法,然后就 A 了……
咱写的 Splay 有一点缺陷,就是每个叶子节点下面还挂着两个不产生贡献的空节点;不过对渐进复杂度都没什么影响,而且可以防止莫名的 RE。
#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;
}