hdu 4699 2个栈维护 or 伸展树 (2013多校联合)
来源:互联网 发布:alex老帅哥淘宝店名 编辑:程序博客网 时间:2024/06/06 02:49
hdu 4699 Editor
题意:对一个数列进行操作,光标位置后面插入一个权值为x的数,删除光标前的那个数,光标左移一位,光标右移一位,求1到k位置的最大的前缀和。。
注意这里的k是在光标之前的,由于这个条件,所以这题又简单的2个栈维护可以解,如果没有这个条件,那么就要用伸展树了。
栈的解法叉姐的解题报告有,我这里说说伸展树的做法, 1.8MS卡过。
我们用cur表示光标在第几个数的右边,size表示数的总个数。
对于操作L: 没有移到最左边就cur--
对于操作R: 没有移到最右边就cur++
对于操作D: 把当前的第cur个位置的节点旋到根,再把第cur-1位置的节点旋到根的左边,令根的左右儿子分别为L,R
那么L一定没有右儿子,把L变为根, R变为L的右儿子。
对于操作I x:把当前的第cur个位置的节点旋到根,在根和根的右儿子之间插入一个新节点。
对于操作Q x:相当于询问1------x区间的最大前缀和。把第0个节点旋到根,把第x-1个节点旋到根的右边。
如何求最大前缀和, 维护一个sum[x]表示区间和,ans[x]表示在x为根的区间里的最大前缀和(注意至少要取一个数)。
伸展树:
#include <cstdio>#include <cstring>#include <algorithm>const int maxn = 1000006;const int inf = 1e9+6;using namespace std;#define L ch[x][0]#define R ch[x][1]#define KT ch[ ch[root][1]][0]int cur, size;struct splaytree { int sz[maxn], ch[maxn][2], pre[maxn]; int tot, root; int sum[maxn], val[maxn], ans[maxn]; int sta[maxn], top; void rotate(int &x, int f) { int y = pre[x], z = pre[y]; ch[y][!f] = ch[x][f]; pre[ch[x][f]] = y; pre[x] = pre[y]; if(z) ch[z][ch[z][1] == y] = x; ch[x][f] = y; pre[y] = x; up(y); } void splay(int &x, int g) { while(pre[x] != g) { int y = pre[x], z = pre[y]; if(z == g) rotate(x, ch[y][0] == x); else { int f = (ch[z][0] == y); ch[y][!f] == x ? rotate(y, f) : rotate(x, !f); rotate(x, f); } } if(!g) root = x; up(x); } void rto(int k, int g) { int x = root; while(sz[L] != k) { if(sz[L] > k) x = L; else { k -= sz[L]+1; x = R; } } splay(x, g); } void newNode(int &x, int v, int fa) { if(top) x = sta[top--]; else x = ++tot; sz[x] = 1; pre[x] = fa; L = R = 0; sum[x] = ans[x] = val[x] = v; } void init() { top = tot = 0; cur = size = 0; newNode(root, -inf, 0); newNode(ch[root][1], -inf, root); } void insert(int k, int v) { rto(k, 0);//debug(); int x; newNode(x, v, root); ch[x][1] = ch[root][1]; if(ch[x][1])pre[ch[x][1]] = x; ch[root][1] = x; up(x); up(root); } void erase(int k) { rto(k, 0); rto(k-1, root); sta[++top] = root; int l = ch[root][0], r = ch[root][1]; root = l; pre[l] = 0; ch[l][1] = r; if(r)pre[r] = l; up(l); } void query(int k) { rto(0, 0); rto(k+1, root); printf("%d\n", ans[KT]); } void up(int x) { sz[x] = sz[L] + sz[R] + 1; sum[x] = sum[L] + sum[R] + val[x]; if(!sz[L]) { ans[x] = max(val[x], val[x]+ans[R]); } else { ans[x] = max(ans[L], sum[L] + max(val[x], 0)); ans[x] = max(ans[x], sum[L]+ val[x]+max(0, ans[R])); } } void print(int x) { printf("node %d, left %d, right %d, pre %d, sum %d, ans %d, val %d\n", x, L, R, pre[x], sum[x], ans[x], val[x]); if(L) print(L); if(R) print(R); } void debug() { printf("root = %d cur = %d size = %d\n", root, cur, size); print(root); } void down(int x) { }}spt;int main() { int m, x; char op[3]; while( ~scanf("%d", &m)) { spt.init(); while(m--) { scanf("%s", op); if(op[0] == 'L') { if(cur)cur--; } else if(op[0] == 'R') { if(cur < size)cur++; } else if(op[0] == 'D') spt.erase(cur--), size--; else { scanf("%d", &x); if(op[0] == 'I') spt.insert(cur++, x), size++; else spt.query(x); } // spt.debug(); } } return 0;}
栈维护:
#include <cstdio>#include <cstring>#include <stack>using namespace std;const int maxn = 1000006;int dp[maxn], sum[maxn], m, x;const int inf = 1e9+6;char op[3];int l[maxn], r[maxn], t1, t2;int main() { while( ~scanf("%d", &m)) { dp[0] = -inf; t1 = t2 = 0; while(m--) { scanf("%s", op); if(op[0] == 'I') { scanf("%d", &x); l[++t1] = x; sum[t1] = sum[t1-1] + x; dp[t1] = max(dp[t1-1], sum[t1]); } else if(op[0] == 'L') { if(!t1) continue; r[++t2] = l[t1--]; } else if(op[0] == 'R') { if(!t2) continue; l[++t1] = r[t2--]; sum[t1] = sum[t1-1] + l[t1]; dp[t1] = max(dp[t1-1], sum[t1]); } else if(op[0] == 'D') t1--; else { scanf("%d", &x); printf("%d\n", dp[x]); } } } return 0;}
- hdu 4699 2个栈维护 or 伸展树 (2013多校联合)
- 伸展树+二分hdu3436(多校联合)
- hdu 4302 Holedox Eating 线段树去维护蛋糕!! 多校联合赛第三题
- 【伸展树】【NOI2005】维护数列
- hdu 4699 Editor(splay tree 伸展树)
- hdu 4699 Editor 伸展树 treap复习
- NOI2005维护数列 伸展树splay
- 2013 多校联合 2 A Balls Rearrangement (hdu 4611)
- HDU 4869 Turn the pokers (2014多校联合训练第一场1009) 解题报告(维护区间 + 组合数)
- 伸展树模版题 hdu
- hdu 4453 Looploop (伸展树)
- hdu 2475 Box(伸展树)
- hdu 4453 Looploop(伸展树)
- HDU 3487(伸展树模板)
- 学习用伸展树解决数列维护问题
- 2013 多校联合 C Partition (hdu 4602)
- 2013 多校联合 I I-number(hdu 4608)
- 2013 多校联合 H Park Visit (hdu 4607)
- sql 表中插入列并赋值
- C/C++ STATIC 用法详解
- 虚继承的具体实现
- 使用SVN对Unity进行版本控制
- 排序操作的执行计划
- hdu 4699 2个栈维护 or 伸展树 (2013多校联合)
- 使用SVN进行Unity3d版本管理总结
- android HTTp文件上传
- usb协议描述
- 更改tomcat端口号的方法
- TabActivity的使用
- form嵌套form问题
- 职场生存法则之五
- 豆瓣音乐下载分析