[HDOJ 4967] Handling the Past [线段树]
来源:互联网 发布:南宁广电网络营业厅 编辑:程序博客网 时间:2024/04/28 22:29
作为一个服务器,你会收到一些关于一个栈的一些操作,他们分别是push,pop,top。由于网络原因,你收到操作的时间和操作实际发送的时间可能时不同的,甚至会是乱序的。
现在每个操作后边都会带着一个时间戳,所有的时间戳均不相同,代表这个操作时何时发送的。要求你对于收到的每一个top操作,立刻返回那个时刻的栈顶元素应该是什么。
观察可以发现,假设把目前收到的所有的操作都按照时间排序,那么对于时间t,返回的栈顶元素就是满足[l,t]区间内push操作恰好比pop操作的个数多1的最靠右的l。
所以我们用一棵线段树,对于push操作,在对应的时间位置上记录+1,pop操作记录-1。那么这棵线段树应该支持的操作有,点修改,查询满足[l,rr]的和等于x的最大的x。
又因为时间戳的范围时int的,所以我们要先进行离散化...
#include <cstdio>#include <map>#include <algorithm>#include <utility>#include <iostream>using namespace std;inline int in() {char c=getchar();while (c<'0'||c>'9') c=getchar();int ans=0;while (c>='0'&&c<='9') {ans=ans*10+c-'0';c=getchar();}return ans;}struct Query {int kind,value,time;void read() {char s[9];scanf("%s",s);if (s[1]=='u') {kind=1;value=in();time=in();} else if (s[1]=='o') {kind=2;time=in();} else {kind=3;time=in();}}};struct SeqNode {SeqNode *ls,*rs;int sum,rsum;void repair() {sum=ls->sum+rs->sum;rsum=max(ls->rsum+rs->sum,rs->rsum);}};SeqNode b[100000],*bp,*root;Query a[50000];map<int,int>c;map<int,int>d;int e[50001];int n;SeqNode *maketree(int l,int r) {SeqNode *ans=bp++;if (l==r) {ans->ls=ans->rs=NULL;ans->sum=ans->rsum=0;} else {int t=(l+r)/2;ans->ls=maketree(l,t);ans->rs=maketree(t+1,r);ans->repair();}return ans;}void set(SeqNode *from,int l,int r,int i,int x) {if (l==r) {from->sum=from->rsum=x;} else {int t=(l+r)/2;if (i<=t) set(from->ls,l,t,i,x);else set(from->rs,t+1,r,i,x);from->repair();}}pair<int,int> get(SeqNode *from,int l,int r,int rr,int sum) {//printf("%d %d %d %d\n",l,r,rr,sum);if (l==r) {if (from->sum==sum) return make_pair(l,0);else return make_pair(-1,from->sum);}int t=(l+r)/2;if (rr<=t) return get(from->ls,l,t,rr,sum);if (rr==r) {if (from->rsum<sum) return make_pair(-1,from->sum);if (from->rs->rsum>=sum) return get(from->rs,t+1,r,r,sum);else return get(from->ls,l,t,t,sum-from->rs->sum);} else {pair<int,int> tmp=get(from->rs,t+1,r,rr,sum);if (tmp.first!=-1) return tmp;if (from->ls->rsum<sum-tmp.second) return make_pair(-1,tmp.second+from->ls->sum);else return get(from->ls,l,t,t,sum-tmp.second);}}void print(SeqNode *from,int l,int r) {if (l!=r) {int t=(l+r)/2;print(from->ls,l,t);print(from->rs,t+1,r);} else {printf("%d ",from->sum);}}void print() {print(root,1,n);printf("\n");}int main() {int i,cas=1;while (scanf("%d",&n),n) {c.clear();d.clear();for (i=0;i<n;i++) {a[i].read();c[a[i].time]=1;d[a[i].time]=i;}i=1;for (map<int,int>::iterator it=c.begin();it!=c.end();it++,i++) {it->second=i;e[i]=it->first;}bp=b;root=maketree(1,n);printf("Case #%d:\n",cas++);//cerr<<cas<<' '<<n<<endl;//print();for (i=0;i<n;i++) {if (a[i].kind==1) {set(root,1,n,c[a[i].time],1);} else if (a[i].kind==2) {set(root,1,n,c[a[i].time],-1);} else {int tmp=get(root,1,n,c[a[i].time],1).first;if (tmp==-1) printf("-1\n");else {printf("%d\n",a[d[e[tmp]]].value);}}//print();//if (i%100==0) cerr<<cas<<' '<<i<<endl;}}return 0;}
0 0
- 【线段树】 HDOJ 4967 Handling the Past
- [HDOJ 4967] Handling the Past [线段树]
- 【HDU】4967 Handling the Past 线段树
- Hdu 4967 Handling the Past (线段树)
- HDU 4967 Handling the past(线段树)
- HDU 4967 Handling the Past 线段树 调用顺序
- HDU-4967 Handling the Past (线段树)
- hdu 4967 Handling the Past 线段树 2014 Multi-University Training Contest 9-1008
- hdu 4967 Handling the Past 线段树,最右正值区间
- HDU 4967(Handling the Past-线段树维护可持久化栈操作)
- HDU 4967 Handling the Past
- hdoj 1556 Color the ball 【线段树】
- HDOJ Color the ball (线段树方法)
- [HDOJ 4348] To the moon [线段树+可持久化]
- hdoj 1556 Color the ball(线段树||树状数组)
- 【线段树】 HDOJ 5381 The sum of gcd
- HDOJ 1556 Color the ball (线段树+区间更新)
- HDOJ 1556 Color the ball(树状数组 & 线段树)
- drawable文件夹详解
- 开源第五周 SIM900模块指令调试+数据传输—乐联平台
- Windows上安装OpenSSL和生成证书
- svn github 中 trunk branches tags 的意思
- 详解IOS开发应用之并发Dispatch Queues
- [HDOJ 4967] Handling the Past [线段树]
- -_-||vs显示行标
- 这个怎么解决
- 如何用在线重定义的方式将普通表变为分区表
- 我所不知道的 Chrome 开发者工具 英文原文:Things I didn’t Know about Chrome DevTools
- Android控件之GridView探究
- sublime text2快捷键整理
- ibus输入法不能随机自动启动
- 黑马程序员—Java中的JDK1.5新特性之枚举