题意:给你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的更多相关文章

  1. Codeforces 719E (线段树教做人系列) 线段树维护矩阵

    题面简洁明了,一看就懂 做了这个题之后,才知道怎么用线段树维护递推式.递推式的递推过程可以看作两个矩阵相乘,假设矩阵A是初始值矩阵,矩阵B是变换矩阵,求第n项相当于把矩阵B乘了n - 1次. 那么我们 ...

  2. 线段树教做人系列(2)HDU 4867 XOR

    题意:给你一个数组a,长度为.有两种操作.一种是改变数组的某个元素的值,一种是满足某种条件的数组b有多少种.条件是:b[i] <= a[i],并且b[1]^b[2]...^b[n] = k的数组 ...

  3. Codeforces 1136E Nastya Hasn't Written a Legend (线段树教做人系列)

    题意:有一个数组a和一个数组k,数组a一直保持一个性质:a[i + 1] >= a[i] + k[i].有两种操作:1,给某个元素加上x,但是加上之后要保持数组a的性质.比如a[i]加上x之后, ...

  4. 线段树教做人系列(3) HDU 4913

    题意及思路看这篇博客就行了,讲得很详细. 下面是我自己的理解: 如果只有2,没有3的话,做法就很简单了,只需要对数组排个序,然后从小到大枚举最大的那个数.那么它对答案的贡献为(假设这个数排序后的位置是 ...

  5. hdu 4521 小明系列问题——小明序列 线段树+二分

    小明系列问题——小明序列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Pro ...

  6. 2018.07.08 hdu4521 小明系列问题——小明序列(线段树+简单dp)

    小明系列问题--小明序列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Proble ...

  7. SPOJ GSS3 线段树系列1

    SPOJ GSS系列真是有毒啊! 立志刷完,把线段树搞完! 来自lydrainbowcat线段树上的一道例题.(所以解法参考了lyd老师) 题意翻译 n 个数, q 次操作 操作0 x y把 Ax 修 ...

  8. hdu 4521 小明系列问题——小明序列(线段树+DP或扩展成经典的LIS)

    小明系列问题--小明序列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Tot ...

  9. [线段树系列] LCT打延迟标记的正确姿势

    这一篇博客将教你什么? 如何用LCT打延迟标记,LCT和线段树延迟标记间的关系,为什么延迟标记要这样打. ——正片开始—— 学习这一篇博客前,确保你会以下知识: Link-Cut-Tree,普通线段树 ...

随机推荐

  1. CodeForces 444C 线段树

    想分块想了很久一点思路都没有,结果一看都是写的线段树= = ...完全忘记了还有线段树这种操作 题意:给一个数组,一种操作是改变l到r为c,还有一种操作是查询l到r的总和差 线段树记得+lazy标记 ...

  2. angularjs 简单指令

    <!DOCTYPE html> <html data-ng-app="app"> <head> <title>angular js& ...

  3. Django 基础 视图系统

    Django的View(视图) 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一个404错误, ...

  4. Codeforces Round #271 (Div. 2)D(递推,前缀和)

    很简单的递推题.d[n]=d[n-1]+d[n-k] 注意每次输入a和b时,如果每次都累加,就做了很多重复性工作,会超时. 所以用预处理前缀和来解决重复累加问题. 最后一个细节坑了我多次: print ...

  5. C++中头文件、源文件之间的区别与联系

    .h头文件和.cpp文件的区别 疑惑1:.h文件能够编写main函数吗? 实验: 编写test.h文件,里面包含main函数 若直接编译g++ test.h -o test,通过file命令 file ...

  6. Python日志统计

    #!/usr/bin/env python # coding:utf-8   import sys,time   class DisplayFormat(object):       def form ...

  7. 场景中GameObject无法用代码隐藏问题(setActive为false)

    GameObject不受代码控制隐藏问题:代码中若对某个gameobject.setActive(false),发现会不起作用,总结下来发现是和object所在模型组的Animator组件的anima ...

  8. SQL夯实基础(一):inner join、outer join和cross join的区别

    一.数据构建 先建表,再说话 create database Test use Test create table A ( AID ,) primary key, name ), age int ) ...

  9. nodejs express mysql

  10. 命令行启动MySQL

    1 首先打开CMD,即命令行 输入mysqld ,如出现 则说明MySQL安装路径下的bin不在系统的环境变量中,你需要进入它的安装路径的bin目录下启动. ps:如果你不知道路径可以去开始菜单,找到 ...