1. 程式人生 > >【HDU4967】Handling the Past

【HDU4967】Handling the Past

區間 題意 ase string con 但是 cout hid style

題意

模擬棧操作。有三種操作push,pop,peak分別代表從棧頂壓入元素,刪除棧頂元素,查詢棧頂元素。但是,每個操作會給出一個時間戳,要求操作必須要按照時間戳來進行。但是對於每個peak必須馬上給出查詢結果。其中n<=50000,xi,ti<=1e9

分析

講真,這種題必須結合樣例才能明白讓幹嘛。如果暴力的話,對於每個peak的時間復雜度都是O(n)。所以我們想到了線段樹。

1.因為t的值很大,所以我們要首先將t離散化(我因為離散化寫醜了一開始還T了好幾發)

2.將每個push的t和x對應的記錄下來

3.對於每個操作push,我們在t的位置插入1,對於每個pop操作,我們在t的位置插入-1。對於每個peak操作,我們找到t左邊的第一個t1,符合sum(t1 to t)>0,這時候和t1對應的x值就是答案。

思路是很好想的,然後就是操作3該怎麽通過線段樹來維護?

我們通過線段樹來維護一個區間和,和一個最大後綴和,然後對於沒個peak查詢,所有從1到t的線段樹的結點,從右往左找,如果加上當前結點的最大後綴和大於0的話,這個答案就一定在這個節點內,否則加上這個結點的區間和繼續往左找。這裏可以結合代碼進行理解。

技術分享圖片
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <vector>
  6
#include <map> 7 8 using namespace std; 9 const int maxn=50000+100; 10 struct Ope{ 11 string name; 12 int t,a; 13 }ope[maxn]; 14 int n,kase; 15 int V[maxn],M[maxn]; 16 int sumv[4*maxn],max_suff[4*maxn]; 17 int v,x; 18 void maintain(int o){ 19 sumv[o]=sumv[2*o]+sumv[2
*o+1]; 20 max_suff[o]=max(max_suff[2*o+1],sumv[2*o+1]+max_suff[2*o]); 21 } 22 void update(int o,int L,int R){ 23 if(L==R){ 24 sumv[o]+=x; 25 max_suff[o]+=x; 26 return ; 27 } 28 int M=L+(R-L)/2; 29 if(v<=M)update(2*o,L,M); 30 if(v>M)update(2*o+1,M+1,R); 31 maintain(o); 32 return; 33 } 34 int tot,ans; 35 int ql,qr; 36 void solve(int o,int L,int R){ 37 if(L==R){ 38 ans=L; 39 return; 40 } 41 int M=L+(R-L)/2; 42 if(tot+max_suff[2*o+1]>0) 43 return solve(2*o+1,M+1,R); 44 tot+=sumv[2*o+1]; 45 return solve(2*o,L,M); 46 } 47 void query(int o,int L,int R){ 48 if(ans!=-1) 49 return; 50 if(ql<=L&&qr>=R){ 51 if(tot+max_suff[o]>0){ 52 solve(o,L,R); 53 } 54 else tot+=sumv[o]; 55 return; 56 } 57 int M=L+(R-L)/2; 58 if(M<qr) 59 query(2*o+1,M+1,R); 60 if(M>=ql) 61 query(2*o,L,M); 62 return; 63 } 64 int main(){ 65 kase=0; 66 while(scanf("%d",&n)!=EOF&&n){ 67 printf("Case #%d:\n",++kase); 68 for(int i=1;i<=n;i++){ 69 cin>>ope[i].name; 70 if(ope[i].name=="push"){ 71 scanf("%d%d",&ope[i].a,&ope[i].t); 72 } 73 if(ope[i].name=="pop"||ope[i].name=="peak"){ 74 scanf("%d",&ope[i].t); 75 } 76 V[i]=ope[i].t; 77 } 78 sort(V+1,V+1+n); 79 for(int i=1;i<=n;i++){ 80 if(ope[i].name=="push"){ 81 int tt=lower_bound(V+1,V+1+n,ope[i].t)-V; 82 M[tt]=ope[i].a; 83 } 84 } 85 /* for(int i=1;i<=n;i++){ 86 int tt=lower_bound(V+1,V+1+n,ope[i].t)-V; 87 cout<<tt<<endl; 88 }*/ 89 90 memset(sumv,0,sizeof(sumv)); 91 memset(max_suff,0,sizeof(max_suff)); 92 93 for(int i=1;i<=n;i++){ 94 if(ope[i].name=="push"){ 95 v=lower_bound(V+1,V+1+n,ope[i].t)-V; 96 x=1; 97 update(1,1,n); 98 } 99 else if(ope[i].name=="pop"){ 100 v=lower_bound(V+1,V+1+n,ope[i].t)-V; 101 x=-1; 102 update(1,1,n); 103 } 104 else{ 105 ql=1,qr=lower_bound(V+1,V+1+n,ope[i].t)-V; 106 tot=0,ans=-1; 107 query(1,1,n); 108 printf("%d\n",ans==-1?-1:M[ans]); 109 } 110 } 111 } 112 return 0; 113 }
View Code

【HDU4967】Handling the Past