从今天起,决定:平衡树、序列操作都用双旋非递归splay,主要是各种特判少,弹性大,应用面广,这点比较爽。
splay参考了很多人的写法,最后决定为了优美,用了struct,儿子指针用了一个数组,感觉还很不错,以前的调试问题,由于现在能够一遍写对了,所以也就不存在了。
双旋采取的是自顶向下式的,也是为了常数着想。
下面就是我的NOI05 sequence代码,以后估计不会再写这个题了,刷过几遍了。
再见,我的SBT。
#include
#include
#include
#include
#define FOR(i,j,k) for (i = (j); i <= (k); ++i)
#define ROF(i,j,k) for (i = (j); i >= (k); --i)
#define oo 0x3F3F3F3F
inline int max (int i, int j){return i > j ? i : j;}
inline void swap (int *i, int *j){static int t; t = *i, *i = *j, *j = t;}
#define maxn 4000050
struct node
{
struct node *c[2];
int key;
int lms, rms, mss, sum, size;
int rev, same;
} x[maxn], *null = x, *root, *ptr = x;
struct node *update (struct node *x)
{
struct node *l = x->c[0], *r = x->c[1];
x->size = l->size + r->size + 1;
x->sum = l->sum + r->sum + x->key;
x->lms = max (l->lms, l->sum + x->key + max (r->lms, 0));
x->rms = max (r->rms, r->sum + x->key + max (l->rms, 0));
x->mss = max (max (r->mss, l->mss), max (l->rms, 0) + x->key + max (r->lms, 0));
return x;
}
void put_rev (struct node *x)
{
if (x == null) return;
swap ((int *)&x->c[0] , (int *)&x->c[1]);
swap (&x->lms , &x->rms);
x->rev ^= 1;
}
void put_same (struct node *x, int t)
{
if (x == null) return;
x->key = t;
x->same = 1;
x->rev = 0;
x->sum = t * x->size;
x->lms = x->rms = x->mss = max (x->sum, t);
}
struct node *push_down (struct node *x)
{
if (x->same)
put_same (x->c[0], x->key), put_same (x->c[1], x->key), x->same = 0;
if (x->rev)
put_rev (x->c[0]), put_rev (x->c[1]), x->rev = 0;
return x;
}
void zig (int d)
{
struct node *t = root->c[d];
root->c[d] = null->c[d];
null->c[d] = root;
root = t;
}
void zigzig (int d)
{
struct node *t = root->c[d]->c[d];
root->c[d]->c[d] = null->c[d];
null->c[d] = root->c[d];
root->c[d] = null->c[d]->c[!d];
null->c[d]->c[!d] = update (root);
root = t;
}
void finish (int d)
{
struct node *p = null->c[d], *q = root->c[!d];
for (; p != null; )
{
p = null->c[d]->c[d];
null->c[d]->c[d] = q;
q = update (null->c[d]);
null->c[d] = p;
}
root->c[!d] = q;
}
void splay (int x)
{
struct node *t; int p;
for ( ; ; )
{
int i = (p = push_down (root)->c[0]->size) < x;
if (p == x || (t = root->c[i]) == null) break;
if (i) x -= p + 1;
int j = (p = push_down (t)->c[0]->size) < x;
if (p == x || t->c[j] == null) {zig (i); break;}
if (j) x -= p + 1;
i != j ? zig (i), zig (j) : zigzig (i);
}
finish (0), finish (1), update (root);
}
struct node *build (int l, int r)
{
if (l > r) return null;
int m = (l + r) >> 1; struct node *t = x + m;
t->c[0] = build (l, m - 1);
t->c[1] = build (m + 1, r);
return update (t);
}
struct node *interval (int pos, int tot)
{
splay (pos - 1);
struct node *bak = root;
root = bak->c[1];
splay (tot);
bak->c[1] = root, root = bak;
return push_down (root->c[1]->c[0]);
}
int main()
{
FILE *fin = fopen ("sequence.in" , "r");
FILE *fout = fopen ("sequence.out", "w");
int n, m, i, pos, tot; char cmd[50];
fscanf (fin, "%d%d", &n, &m);
*null = (struct node){{null, null}, -oo, -oo, -oo, -oo};
(++ptr)->key = -oo;
FOR (i, 1, n)
fscanf (fin, "%d", &((++ptr)->key));
(++ptr)->key = -oo;
root = build (1, n + 2);
ROF (m, m, 1)
{
fscanf (fin, "%s", cmd);
switch (cmd[2])
{
case 'S':
fscanf (fin, "%d%d", &pos, &tot);
struct node *t = ptr;
FOR (i, 1, tot)
fscanf (fin, "%d", &((++ptr)->key));
interval (pos + 1, 0);
root->c[1]->c[0] = build (t - x + 1, ptr - x);
break;
case 'L': fscanf (fin, "%d%d", &pos, &tot); interval (pos, tot); root->c[1]->c[0] = null; break;
case 'K': fscanf (fin, "%d%d%d", &pos, &tot, &i); put_same (interval (pos, tot), i); break;
case 'V': fscanf (fin, "%d%d", &pos, &tot); put_rev (interval (pos, tot)); break;
case 'T': fscanf (fin, "%d%d", &pos, &tot); fprintf (fout, "%d\n", interval (pos, tot)->sum); break;
case 'X': fprintf (fout, "%d\n", root->mss); break;
}
update (root->c[1]), update (root);
}
fclose (fin);
fclose (fout);
return 0;
}