hdu 4699 Editor 伸展树 treap复习

来源:互联网 发布:锐思数据库 编辑:程序博客网 时间:2024/05/01 15:13

题意:对一个数列进行操作,光标位置后面插入一个权值为x的数,删除光标前的那个数,光标左移一位,光标右移一位,求1到k位置的最大的前缀和。。


思路:注意这里的k是在光标之前的,由于这个条件,所以这题又简单的2个栈维护可以解,如果没有这个条件,那么就要用伸展树了。之前写过这题题解,数组的splay和栈都写过 以前的链接

其它操作都没问题,这里主要讲讲 询问操作。

对于操作Q x:相当于询问1------x区间的最大前缀和。把第0个节点旋到根,把第x-1个节点旋到根的右边。

如何求最大前缀和, 每个节点维护一个sum表示区间和,ans表示在为根的区间里的最大前缀和(注意至少要取一个数)。写个pushup更新ans即可。


splay:这题主要是为了 给我的新版splay练手, 新版的splay有很大改进, 大大缩短了rotate, splay函数的成型时间,减少了错误率,而且代码简洁。


treap:用可持久化思想的那种treap, 相比splay而言,insert, delete, query操作更加顺手, 在splay中写这些操作时不时会出现错误。 这种treap其实可以实现与splay一样的功能,包括有 pushdown的一些问题,成段插入, 成段删除等,总体来说写treap会更省事省力。


2份代码在下面:

splay code:

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 1000006;struct node;node *root, *null;struct node {node *c[2], *fa;int sz, id; //id表示在内存中节点的标号,方便debugint val, sum, ans;inline bool d() {return fa->c[1] == this;}inline void fix(int d, node *x) { //修改节点父亲儿子关系c[d] = x, x->fa = this;}void rot() { //把this节点 上旋node *y = fa, *z = y->fa;bool f = d();z->fix(y->d(), this);y->fix(f, c[!f]);fix(!f, y);y->up();}void splay(node *g) { //把this节点旋到g节点下面while (fa != g) {node *y = fa, *z = y->fa;if(z == g) rot();else if(y->d() == d()) y->rot(), rot(); //3点共线else rot(), rot();   }up();if(g == null) root = this;}void up() {sz = c[0]->sz + c[1]->sz + 1;sum = c[0]->sum + c[1]->sum + val;if(c[0] == null) ans = val + max(0, c[1]->ans);else ans = max(c[0]->ans, c[0]->sum + val + max(0, c[1]->ans));}void out() {  //输出节点信息,debug用printf("v%d fa%d ls%d rs%d lsz%d rsz%d val%d sum%d ans%d\n", id, fa->id, c[0]->id,c[1]->id, c[0]->sz, c[1]->sz, val, sum, ans);}};struct splayTree {node mem[maxn];int tot;node* newNode(int v = 0, node *fa = null) {node *x = &mem[tot];x->val = x->sum = x->ans = v;x->sz = 1, x->id = tot++;x->fa = fa;x->c[0] = x->c[1] = null;return x;}void rto(int k, node *g) {k++; //一开始有一个最小的节点node *x = root;while (true) {int v = x->c[0]->sz + 1;if(v == k) break;if(k > v) {k -= v;x = x->c[1];} else x = x->c[0];}x->splay(g);}//分界线, 以上代码原封不动#define kt root->c[1]->c[0]     void init() { //初始化新建最小点和最大点cur = size = tot = 0;null = newNode(), null->sz = 0;root = newNode();root->c[1] = newNode(0, root);root->up();}void ins(int k, int v) {rto(k, null);node *x = newNode(v, root);x->fix(1, root->c[1]);root->fix(1, x);x->up(), root->up();}void del(int k) {rto(k - 1, null);rto(k, root);root->fix(1, root->c[1]->c[1]);root->c[1]->up(), root->up();}int query(int k) {rto(0, null);rto(k + 1, root);return kt->ans;}void show(node *x) { //debug用if(x == null) return;x->out();show(x->c[0]);show(x->c[1]);}void show() { //debug用puts("************");printf("root:%d\n", root->id);show(root);}}t;int cur, size;int main() {int m;while (~scanf("%d", &m)) {t.init();char op[3];int v;while (m--) {scanf("%s", op);if(op[0] == 'L' && cur) cur--;if(op[0] == 'R' && cur != size) cur++;if(op[0] == 'D') t.del(cur), cur--, size--;if(op[0] == 'Q') {scanf("%d", &v);printf("%d\n", t.query(v));}if(op[0] == 'I') {scanf("%d", &v);t.ins(cur, v);size++, cur++;}}}return 0;}

treap code:

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;struct node;node *null, *root;struct node {node *c[2];int val, ans, sum;int sz, r;inline void up() {sz = c[0]->sz + c[1]->sz + 1;sum = c[0]->sum + c[1]->sum + val;if(c[0] == null) ans = val + max(0, c[1]->ans);else ans = max(c[0]->ans, c[0]->sum + val + max(0, c[1]->ans));}};const int maxn = 100005;node mem[maxn];int tot;node* newNode(int v = 0) {node *x = &mem[tot++];x->val = x->sum = x->ans = v;x->c[0] = x->c[1] = null;x->sz = 1, x->r = rand();return x;}void merge(node *&o, node *a, node *b) {if(a == null) o = b;else if(b == null) o = a;else if(a->r < b->r) {o = a;merge(o->c[1], a->c[1], b);o->up();} else {o = b;merge(o->c[0], a, b->c[0]);o->up();}}void split(node *o, node *&a, node *&b, int k) {if(!k) {a = null;b = o;} else if(o->sz <= k) {a = o;b = null;} else if(o->c[0]->sz >= k) {b = o;split(o->c[0], a, b->c[0], k);b->up();} else {a = o;split(o->c[1], a->c[1], b, k - o->c[0]->sz - 1);a->up();}}void out(node *x) {    if(x == null) return;    printf("%d\n", x->val);    out(x->c[0]);    out(x->c[1]);}void ins(int k, int v) {node *a, *b, *c;split(root, a, b, k);out(a);// out(b);c = newNode(v);merge(a, a, c);merge(root, a, b);}void del(int k) {node *a, *b, *c;split(root, a, b, k - 1);split(b, b, c, 1);merge(root, a, c);}int query(int k) {node *a, *b, *c;split(root, a, b, k);int ret = a->ans;merge(root, a, b);return ret;}int cur, size;void init() {cur = tot = size = 0;null = newNode(), null->sz = 0;root = null;}int main() {int m;while (~scanf("%d", &m)) {init();char op[3];int v;while (m--) {scanf("%s", op);if(op[0] == 'L' && cur) cur--;if(op[0] == 'R' && cur != size) cur++;if(op[0] == 'D') del(cur), cur--, size--;if(op[0] == 'Q') {scanf("%d", &v);printf("%d\n", query(v));}if(op[0] == 'I') {scanf("%d", &v);ins(cur, v);size++, cur++;}}}return 0;}


3 0
原创粉丝点击