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多校联合)相关推荐

  1. 2013 多校联合4 1011 Fliping game (hdu 4642)

    题意:在一个矩阵中放着可上可下的银币,你可以翻一个矩形里面的银币使它们变成相反的方向,但此矩型必须是右下角是矩阵的最右下角,左上角这个点必须是朝上的.最 后结束的标志是所有的银币都已经都是朝上的,此时 ...

  2. hdu 4699 Editor(splay tree 伸展树)

    hdu 4699  Editor 题意:对一个数列进行操作,光标位置后面插入一个权值为x的数,删除光标前的那个数,光标左移一位,光标右移一位,求到k位置的最大的前缀和.. 解题思路:标乘是用了栈进行维 ...

  3. CF1621G Weighted Increasing Subsequences(离散化+树状数组优化dp+栈维护后缀最大值+计数)

    problem luogu-link solution 显然单独考虑每个 iii 的贡献,即被多少个合法上升子序列包含. 令 x=max⁡{j∣j>i∧aj>ai}x=\max\{j\ | ...

  4. 【BZOJ3879】SvT,后缀数组+单调栈维护sum

    Time:2016.08.15 Author:xiaoyimi 转载注明出处谢谢 如果有不明白的地方可以在下面评论问我 传送门 思路: 建立后缀数组求出Height 如果说对每次询问暴力求LCP累加的 ...

  5. Splay伸展树入门(单点操作,区间维护)附例题模板

    Pps:终于学会了伸展树的区间操作,做一个完整的总结,总结一下自己的伸展树的单点操作和区间维护,顺便给未来的自己总结复习用. splay是一种平衡树,[平均]操作复杂度O(nlogn).首先平衡树先是 ...

  6. Flutter全局路由封装及路由栈维护

    目录 1. 路由选择 2. 需要解决的问题 2. 源码分析 1. 路由选择 Flutter路由跳转方式有如下两种: 基本路由 Navigator.of(context).push(MaterialPa ...

  7. [置顶] hdu 1890 伸展树区间翻转

    题意: 给你n个数,每次先输出第i大的数的位置(如果有多个,选下标小的那个),然后每次将第i个位置到第i大的数所在位置之间的数进行翻转. 思路:输入的数组可能有多个相同的值,我们可以进行两次排序把数组 ...

  8. PHP算法 《树形结构》 之 伸展树(1) - 基本概念

    伸展树的介绍 1.出处:http://dongxicheng.org/structure/splay-tree/ A. 概述 二叉查找树(Binary Search Tree,也叫二叉排序树,即Bin ...

  9. 伸展树(Splay tree)浅谈

    树看的越来越多,越来越神奇. 看伸展树这种神级数据结构之前,建议大家首先彻底明白二叉搜索树,这是万树的基础. 然后可以去看下treap,最好再去看下红黑树.如果有线段树的基础那更好了,我们会发现线段树 ...

最新文章

  1. p2148 [SDOI2009]ED
  2. 怎样使用element-starter快速搭建ElementUI项目
  3. linux服务器文件偶尔丢失,【服务器运维】linux抛出找不到文件非常的解决方法...
  4. java中的方法求和_在Java中模拟求和类型的巧妙解决方法
  5. yaf 重写index.php,php框架Yaf路由重写实例代码
  6. 【Docker】练习-在容器中部署静态网站
  7. 计算机文化基础说课ppt,计算机文化基础说课 -_图文.ppt
  8. 团队作业9——项目验收与总结
  9. unbuntu设置iptables
  10. 科学计算机r系数的操作,相关系数,确定系数(R^2)计算公式与在线计算器_三贝计算网_23bei.com...
  11. 爆流的随便画教程—NO12 画嘞个剑
  12. 微信小程序html格式转换详解
  13. ssssssssssssssss
  14. 痛彻心扉:学了半年 Python,还是找不到工作!
  15. 冲刺!这篇 1658 页的《Java 面试突击核心讲》学明白保底年薪 30w
  16. 学生用计算机房预算表,机房配置清单预算.doc
  17. 端口号被占用的解决方法
  18. OD 调试多线程遇到的问题以及解决方法
  19. 10+ 张图解|高并发分布式架构演进
  20. 商务印书馆汉译世界学术名著丛书目录

热门文章

  1. static属性能用@Autowired注入吗?
  2. 洛谷p2504 HAOI2006 聪明的猴子
  3. java课程设计实验报告_java课程设计实验报告样例
  4. 感谢我的联科数据女神-----董禹
  5. 计算机病毒常见病状,电脑中病毒常见的10种症状
  6. 桌面自动化-SuperPatrick工具使用初探
  7. 《UNIX/Linux的传奇历史》--程序员价值观(送给年轻程序员)
  8. 三十二、数据库相关3
  9. mini2440视频监控
  10. 烟锁重楼,情缘若梦终是空