hdu 4699  Editor

题意:对一个数列进行操作,光标位置后面插入一个权值为x的数,删除光标前的那个数,光标左移一位,光标右移一位,求到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;
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, 0, 0);
newNode(ch[root][1], 0, root);
}
void insert(int k, int v) {
rto(k, 0);
//debug();
int x;
newNode(x, v, root);
ch[x][1] = ch[root][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;
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];
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\n", root, cur);
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 伸展树的更多相关文章

  1. HDU 4699 - Editor - [对顶栈]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4699 Problem Description Sample Input8I 2I -1I 1Q 3LD ...

  2. hdu 4699 Editor 模拟栈

    思路:刚开始用STL中的栈,一直RE……,之后改为手动模拟栈操作,在注意点细节就可以了!!! 代码如下: #include<cstdio> #include<cstring> ...

  3. HDU 5033 Building(单调栈维护凸包)

    盗张图:来自http://blog.csdn.net/xuechelingxiao/article/details/39494433 题目大意:有一排建筑物坐落在一条直线上,每个建筑物都有一定的高度, ...

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

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

  5. [置顶] hdu 4418 高斯消元解方程求期望

    题意:  一个人在一条线段来回走(遇到线段端点就转变方向),现在他从起点出发,并有一个初始方向, 每次都可以走1, 2, 3 ..... m步,都有对应着一个概率.问你他走到终点的概率 思路: 方向问 ...

  6. hdu 1754 I Hate It (splay tree伸展树)

    hdu 1754 I Hate It 其实我只是来存一下我的splay模板的..请大牛们多多指教 #include<stdio.h> #include<string.h> #i ...

  7. [置顶] ※数据结构※→☆线性表结构(stack)☆============栈 序列表结构(stack sequence)(六)

    栈(stack)在计算机科学中是限定仅在表尾进行插入或删除操作的线性表.栈是一种数据结构,它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据.栈 ...

  8. HDU - 4699 对顶栈

    Get到了全新O(1)替代部分伸展树功能的姿势 左栈stk1维护当前信息,右栈stk2维护历史删除信息 题目求的是严格的前缀和(且小于当前指针)那就每次左栈新增时再更新前缀和信息就好 即使把题面换成最 ...

  9. 【HDU 4699】 Editor

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4699 [算法] 维护两个栈,一个栈放光标之前的数,另外一个放光标之后的数 在维护栈的同时求最大前缀 ...

随机推荐

  1. Linux下select函数的使用

    一.Select 函数详细介绍 Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect. accept.recv ...

  2. 我在北京找工作(五):备战阿里巴巴java笔试<1>:筑基

    @@@2013年9月11日 还在北京昌平区@@@ 好几天没有往博客上贴我的面试备战笔记了,今天开始分享一下备战阿里巴巴校招的笔经,当然重点是java方向的题目~. 插一段2014年阿里巴巴校招的消息: ...

  3. ORACLE 五种表的优缺点总结

    ORACLE 五种表的优缺点总结: 1.普通表(heap table):适合大部分设计场景,有长处也有缺点. 长处: a,语法简单方便 b,适合大部分场景 缺点: a,更新日志开销较大 b,Delet ...

  4. Linux 高性能server编程——高级I/O函数

    重定向dup和dup2函数 #include <unistd.h> int dup(int file_descriptor); int dup2(int file_descriptor_o ...

  5. 【OpenMesh】Some basic operations: Flipping and collapsing edges

    这一节中你将学到一些OpenMesh中早已提供的基础操作. 内容包括三角形网格边的翻转以及通过连接邻接的顶点边缘折叠. 三角形网格的翻转(Flipping edges) 考虑到两个邻接面的三角形网格中 ...

  6. Xamarin.forms 自定义tabview控件

    一 问题描述 forms本身ui代码是翻译为平台原生代码,forms按照xaml技术进行对android和ios两种ui模型进行公共抽象出了几种page和view,在空杯博客已经有详细介绍 http: ...

  7. [置顶] dubbo管理控制台安装

    dubbo管理控制台开源部分主要包含:路由规则,动态配置,服务降级,访问控制,权重调整,负载均衡,等管理功能. 1.下载dubbo 地址:http://code.alibabatech.com/mvn ...

  8. Delphi事件的广播2

    上篇文章写了将事件分离成类的方法来实现事件的广播,这次将参考观察者模式来实现事件的广播.模式中主要有这两个角色: 发布者:发布者保存着一张观察者的列表,以便在必要的时候调用观察者的方法. 观察者:观察 ...

  9. 《Head First 设计模式》学习笔记——模板方法模式

    模板方法模式是类的行为模式.准备一个抽象类,将部分逻辑以详细方法以及详细构造函数的形式实现.然后声明一些抽象方法来迫使子类实现剩余的逻辑.不同的子类能够以不同的方式实现这些抽象方法,从而对剩余的逻辑有 ...

  10. 有关于web server架构的一个小疑问

    今天闲的时候trace route了yahoo和sina的域名,yahoo的如下: 1     1 ms     1 ms    <1 ms  172.21.127.1   2     3 ms ...