线段树教做人系列(1)HDU4967 Handling the Past
题意:给你n组操作,分别为压栈,出栈,询问栈顶元素。每一组操作有一个时间戳,每次询问栈顶的元素的操作询问的是在他之前出现的操作,而且时间戳小于它的情况。题目中不会出现栈为空而且出栈的情况。
例如:
push 100 1
peak 6
push 200 5
询问的结果是100。
思路:先把时间戳离散化,我们把压栈看成在这个操作所在的时间+1,出栈看成-1,那么询问操作可以看成从询问的时间开始,找一段最短的后缀,并且后缀和大于0。所以我们在线段树中维护区间和和后缀和,查询的时候先搜索右半区间,如果右半区间的后缀和小于0,那把右半区间的和加上,再去查询左半区间。
代码:
#include <bits/stdc++.h>
#define ls(x) (x << 1)
#define rs(x) ((x << 1) | 1)
using namespace std;
const int maxn = 50010;
int ans;
struct op {
int id, time, val;
}; op a[maxn];
int mp1[maxn], mp2[maxn], b[maxn];
struct SegementTree {
int psum, sum;
}; SegementTree tr[maxn * 4]; void maintain(int o) {
tr[o].sum = tr[ls(o)].sum + tr[rs(o)].sum;
tr[o].psum = max(tr[rs(o)].psum, tr[rs(o)].sum + tr[ls(o)].psum);
} void init(int o, int l, int r) {
if(l == r) {
tr[o].sum = tr[o].psum = 0;
return;
}
int mid = (l + r) >> 1;
init(ls(o), l ,mid);
init(rs(o), mid + 1, r);
maintain(o);
} void insert(int o, int l, int r, int pos, int val) {
if(l == r) {
tr[o].sum += val;
tr[o].psum += val;
return;
}
int mid = (l + r) >> 1;
if(pos <= mid) insert(ls(o), l, mid, pos, val);
else insert(rs(o), mid + 1, r, pos, val);
maintain(o);
} int query(int o, int l, int r, int ql, int qr, int now) {
int tmp = 0;
if(ql <= l && r <= qr) {
if(tr[o].psum + now <= 0) return tr[o].sum;
else {
if(l == r) {
ans = l;
return tr[o].sum;
}
}
}
int mid = (l + r) >> 1;
if(qr > mid) tmp = query(rs(o), mid + 1, r, ql, qr, now);
if(ans != -1) return tmp;
tmp += query(ls(o), l, mid, ql, qr, now + tmp);
return tmp;
}
char s[10];
int main() {
int n, x, y, kase = 0;
while(~scanf("%d", &n) && n) {
init(1, 1, n);
for (int i = 1; i <= n; i++) {
scanf("%s", s + 1);
if(s[2] == 'u') {
scanf("%d%d", &x, &y);
a[i] = (op){1, y, x};
b[i] = y;
} else if(s[2] == 'o') {
scanf("%d", &x);
a[i] = (op){2, x, 0};
b[i] = x;
} else {
scanf("%d", &x);
a[i] = (op){3, x, 0};
b[i] = x;
}
}
sort(b + 1, b + 1 + n);
for (int i = 1; i <= n; i++) {
int pos = lower_bound(b + 1, b + 1 + n, a[i].time) - b;
mp1[pos] = i;
mp2[i] = pos;
}
printf("Case #%d:\n", ++kase);
for (int i = 1; i <= n; i++) {
if(a[i].id == 1)
insert(1, 1, n, mp2[i], 1);
else if(a[i].id == 2)
insert(1, 1, n, mp2[i], -1);
else {
ans = -1;
query(1, 1, n, 1, mp2[i], 0);
if(ans == -1) printf("-1\n");
else printf("%d\n", a[mp1[ans]].val);
}
}
}
}
线段树教做人系列(1)HDU4967 Handling the Past的更多相关文章
- Codeforces 719E (线段树教做人系列) 线段树维护矩阵
题面简洁明了,一看就懂 做了这个题之后,才知道怎么用线段树维护递推式.递推式的递推过程可以看作两个矩阵相乘,假设矩阵A是初始值矩阵,矩阵B是变换矩阵,求第n项相当于把矩阵B乘了n - 1次. 那么我们 ...
- 线段树教做人系列(2)HDU 4867 XOR
题意:给你一个数组a,长度为.有两种操作.一种是改变数组的某个元素的值,一种是满足某种条件的数组b有多少种.条件是:b[i] <= a[i],并且b[1]^b[2]...^b[n] = k的数组 ...
- Codeforces 1136E Nastya Hasn't Written a Legend (线段树教做人系列)
题意:有一个数组a和一个数组k,数组a一直保持一个性质:a[i + 1] >= a[i] + k[i].有两种操作:1,给某个元素加上x,但是加上之后要保持数组a的性质.比如a[i]加上x之后, ...
- 线段树教做人系列(3) HDU 4913
题意及思路看这篇博客就行了,讲得很详细. 下面是我自己的理解: 如果只有2,没有3的话,做法就很简单了,只需要对数组排个序,然后从小到大枚举最大的那个数.那么它对答案的贡献为(假设这个数排序后的位置是 ...
- hdu 4521 小明系列问题——小明序列 线段树+二分
小明系列问题——小明序列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Pro ...
- 2018.07.08 hdu4521 小明系列问题——小明序列(线段树+简单dp)
小明系列问题--小明序列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Proble ...
- SPOJ GSS3 线段树系列1
SPOJ GSS系列真是有毒啊! 立志刷完,把线段树搞完! 来自lydrainbowcat线段树上的一道例题.(所以解法参考了lyd老师) 题意翻译 n 个数, q 次操作 操作0 x y把 Ax 修 ...
- hdu 4521 小明系列问题——小明序列(线段树+DP或扩展成经典的LIS)
小明系列问题--小明序列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Tot ...
- [线段树系列] LCT打延迟标记的正确姿势
这一篇博客将教你什么? 如何用LCT打延迟标记,LCT和线段树延迟标记间的关系,为什么延迟标记要这样打. ——正片开始—— 学习这一篇博客前,确保你会以下知识: Link-Cut-Tree,普通线段树 ...
随机推荐
- spring boot 基础篇 -- 定时任务
在日常项目中,常常会碰到定时监控项目中某个业务的变化,下面是spring boot 集成的定时任务具体配置: @Component public class IndexWarningScheduled ...
- mysql插入一万条数据
定义一个存储过程 mysql> delimiter $$ mysql> create procedure ptest() -> begin -> declare p ...
- C# WebApi 配置复杂路由不生效的问题
配置复杂路由不生效是由于优先级的关系,应该把默认路由放在最后. config.Routes.MapHttpRoute( name: "DynamicApi", routeTempl ...
- 分析 PHP升级导致系统负载过高问题(转载)
原文:http://chuansongme.com/n/797172 背景 据XX部门兄弟反应, 其在将PHP从5.3.8 升级到5.5.13 时, 开始运行正常, 运行一段时间后, 系统负载变高,达 ...
- string类的常用功能演示
这个程序可用随着我对string的用法的增多而有调整. /* 功能说明: string类的常用功能演示. 实现方式: 主要是演示string的常用函数的用法和它与字符数组的区别与联系 限制条件或者存在 ...
- sort--Linux下文本处理五大神器之三
转自:http://www.cnblogs.com/dong008259/archive/2011/12/08/2281214.html sort命令是帮我们依据不同的数据类型进行排序,其语法及常用参 ...
- LeetCode Maximum Average Subarray I
原题链接在这里:https://leetcode.com/problems/maximum-average-subarray-i/description/ 题目: Given an array con ...
- 创建Task的多种方法
Gradle的Project从本质上说只是含有多个Task的容器,一个Task与Ant的Target相似,表示一个逻辑上的执行单元. 我们可以通过多种方式定义Task,所有的Task都存放在Proje ...
- phpstorm下载和破解
http://idea.qinxi1992.cn/ 官网下载对应版本,在下面进行破解! storm官网:https://www.jetbrains.com/phpstorm/ 破解网址 :http: ...
- eclipse -- propedit 安装.
SSH 项目中.用到国际化文件,Message.properties 但里面的文本都是 unicode 格式的,用起来不谁.而且也不想通过其它工具转码来使用. 可以通过安装 eclipse 的 pro ...