【线段树】codeforces R159E. Greedy Elevator
http://codeforces.com/contest/257/problem/E
闲来无事切一下div2的比赛,增强一下自信心,弱暴了=。=,最近卡题卡得要靠div2来涨信心了。
E题题面很长,但是实际很好读,读完题发现就是一个纯粹的模拟题,不过规模比较大需要用数据结构来维护,一开始觉得平衡树挺方面的,后来发现楼层之后10^5离散化都不用就写成线段树了。
由于电梯运行时间可能很大,所以不能以秒为单位模拟,但是显然可以以请求电梯以及下电梯的事件来模拟,用线段树判断当前向下的请求以及向上请求总数,判断电梯运行方向,同时顺便求出以该方向运行多久可以满足第一个请求,再于新增加请求时间比较看看哪个事件先发生。。最多2*n个事件,同时每次判断时间复杂度O(logn)
View Code
1 //By Lin 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<map> 6 #include<vector> 7 #define maxn 100010 8 #define foreach(a,b) for(__typeof(b.begin()) a = b.begin(); a!=b.end(); a++ ) 9 #define Rep(i,n) for(int i = 0; i<n; i++) 10 using namespace std; 11 typedef long long LL; 12 13 struct Segtree{ 14 int left[maxn*4],right[maxn*4]; 15 int L[maxn*4],R[maxn*4]; 16 int sum[maxn*4]; 17 void build(int l,int r,int step){ 18 left[step] = l , right[step] = r; 19 sum[step] = 0; 20 L[step] = R[step] = -1; 21 if ( l == r ) return; 22 int mid = (l+r)/2; 23 build( l , mid , step*2 ); 24 build(mid+1, r , step*2+1 ); 25 } 26 void updata(int w,int num,int step){ 27 if ( left[step] == right[step] ){ 28 sum[step] += num; 29 L[step] = R[step] = sum[step]?w:-1; 30 return; 31 } 32 int mid = ( left[step]+right[step])/2; 33 updata( w , num , w<=mid?(step*2):(step*2+1) ); 34 sum[step] = sum[step*2] + sum[step*2+1]; 35 L[step] = L[step*2+(L[step*2]==-1?1:0)]; 36 R[step] = R[step*2+(R[step*2+1]==-1?0:1)]; 37 } 38 int ask(int l,int r,int &g ,int &h,int step){ 39 if ( left[step] == l && right[step] == r ){ 40 g = L[step] , h = R[step]; 41 return sum[step]; 42 } 43 int mid = ( left[step]+right[step])/2; 44 if ( r<=mid ) return ask(l,r,g,h,step*2); 45 else if ( l > mid ) return ask(l,r,g,h,step*2+1); 46 else{ 47 int g1,g2,h1,h2; 48 int ret = ask(l,mid,g1,h1,step*2)+ask(mid+1,r,g2,h2,step*2+1); 49 g = g1!=-1?g1:g2; 50 h = h2!=-1?h2:h1; 51 return ret; 52 } 53 } 54 }tree; 55 56 int n,m; 57 struct People{ 58 int t,s,f,id; 59 void init(int _id){ 60 id = _id; 61 scanf("%d%d%d", &t, &s, &f ); 62 } 63 bool friend operator<( const People &a, const People &b){ 64 return a.t<b.t; 65 } 66 }data[maxn]; 67 68 map<int,vector<int> > mm; 69 LL ans[maxn],now; 70 71 void updata(int cur){ 72 // printf("updata %d\n", cur ); 73 foreach( iter , mm[cur] ){ 74 // printf("iter %d\n" , *iter ); 75 int k = *iter; 76 if ( k >= 0 ) { 77 mm[data[k].f].push_back( -data[k].id ); 78 tree.updata( data[k].f, 1, 1); 79 } 80 else 81 ans[-k] = now; 82 } 83 // printf("%d %d\n" , cur , -((int)mm[cur].size()) ); 84 tree.updata( cur , -((int)mm[cur].size()), 1 ); 85 mm[cur].clear(); 86 } 87 int main(){ 88 scanf("%d%d", &n, &m ); 89 tree.build(1,m,1); 90 Rep(i,n) data[i].init(i+1); 91 sort( data , data+n ); 92 // printf("ok\n"); 93 int cur = 1, i = 0,g1,h1,g2,h2; 94 while ( true ){ 95 int num1 = tree.ask(1,cur,g1,h1,1), 96 num2 = tree.ask(cur,m,g2,h2,1); 97 // printf("%d %lld (%d %d %d) (%d %d %d)\n" , cur , now ,num1,g1,h1,num2,g2,h2 ); 98 if ( num1 > num2 ){ 99 if ( i<n && data[i].t<=now+cur-h1 ){ 100 cur = cur-(data[i].t-now); 101 now = data[i].t; 102 mm[data[i].s].push_back(i); 103 tree.updata( data[i].s , 1 , 1 ); 104 i++; 105 continue; 106 } 107 now += cur-h1; 108 cur = h1; 109 updata(cur); 110 } 111 else if ( num1 <= num2 && num2 ){ 112 if ( i<n && data[i].t<=now+g2-cur ){ 113 cur = cur+(data[i].t-now); 114 now = data[i].t; 115 mm[data[i].s].push_back(i); 116 tree.updata( data[i].s , 1 , 1 ); 117 i++; 118 continue; 119 } 120 now += g2-cur; 121 cur = g2; 122 updata(cur); 123 } 124 else{ 125 if ( i == n ) break; 126 now = data[i].t; 127 mm[data[i].s].push_back(i); 128 tree.updata( data[i].s , 1 , 1 ); 129 i++; 130 } 131 } 132 Rep(i,n) printf("%I64d\n", ans[i+1] ); 133 return 0; 134 }