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. ARC内存使用注意事项

    官方介绍: https://developer.apple.com/library/mac/#documentation/Performance/Conceptual/ManagingMemory/M ...

  2. excel使用cube

  3. 第五天学习内容 for循环,嵌套

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...

  4. EasyUI - 使用一般处理程序 HttpHandler (.ashx)

    以easyui中的panel中,使用url加载数据为列. 效果: html代码: <div id="p" style="padding: 10px;"&g ...

  5. 【ASP.NET Web API教程】2.3.2 创建域模型

    原文:[ASP.NET Web API教程]2.3.2 创建域模型 Part 2: Creating the Domain Models 第2部分:创建域模型 本文引自:http://www.asp. ...

  6. 基于visual Studio2013解决面试题之0209最大堆排序

     题目

  7. doT js模板入门

    doT.js github地址: doT.js 官方站点 实例1:简单 <!DOCTYPE html> <html lang="en"> <head& ...

  8. tsunami:一种基于UDP协议的高速传输

    一. 需求 近期在做数据库迁移.常常须要打包实例传输.传统scp感觉非常慢. 二. 软件信息 1. 软件主页:http://tsunami-udp.sf.net/ 2. 软件安装:直接源代码make ...

  9. JavaScript权威指南科20章 client记忆

    20 client记忆 client几种形式存储的: web记忆 cookie IE userData 离线应用 web数据库 文件系统api 20.1 localStorage 和 sessionS ...

  10. Mac OS升级到Yosemite后一些问题

    苹果"优山美地"採用移动设备平面风格,看起来还是相当清爽. 只是升级完还是有一些程序兼容性问题的. 1. 开发Android的程序猿们,Java se 6 须要升级到2014_00 ...