BZOJ 1503 郁闷的出纳员 treap
真的,想引用一下另外以为大神的博客, 这道题改成郁闷的博主好了, (调了3个小时后弃疗)。 不过这道题之所以没能写好,我觉得有个原因也是经验不够,太单纯了,题目叫我脚上某个数,减去某个数,难道我就真的去加去减吗(肯定TLE的)? 看了别人的博客,我才恍然大悟,有延时操作这种神奇的东西。 简单形容一下这道题的延时操作吧! 假设最低工资标准为 low, 用一个变量a, 如果要对数列加上某个数b 的话, 就 a += b, 如果要减去某个数 b , 就 a -= b, 删除的时候要怎么办呢? 这是要删去比 low - a 小的数,(因为如果a为正意味着数列中的数加上了a,其实相当于最低工资标准减去a)。 那如果要插入某个数b呢! 就要插入 b - a; 因为a是对之前的值处理的结果,与b无关,而接下来要把b和之前的值一视同仁,所以要减去,即把b插入队列后,b会自动加上a,所以要把a减去。
这就是延时操作。另外一个就是删除操作,其实也不难(真不明白,一开始为什么我要把函数写成没返回值的而且直接处理后赋值就行了, 我干嘛把右节点旋上来,傻啊!)too young too simple。
加油!看来还得多练(还有要看题,人家明明说了,如果初始工资小于最低工资标准,人家会离开的。我哭了TAT)
1 #include<cstdio> 2 #include<iostream> 3 #include<cstdlib> 4 #define rep(i,j,k) for(int i = j; i <= k; i++) 5 #define maxn 100005 6 #define lc tr[k].c[0] 7 #define rc tr[k].c[1] 8 using namespace std; 9 10 int read() 11 { 12 int s = 0 , t = 1 ; char c = getchar(); 13 while( !isdigit(c) ){ 14 if( c == '-' ) t = -1; c =getchar(); 15 } 16 while( isdigit(c) ){ 17 s = s * 10 + c -'0'; c = getchar(); 18 } 19 return s * t; 20 } 21 22 struct tree{ 23 int c[2], v, s, rd; 24 } tr[maxn]; 25 int cnt = 0; 26 27 void maintain(int x) 28 { 29 if( !x ) return; 30 tr[x].s = tr[tr[x].c[0]].s + tr[tr[x].c[1]].s + 1; 31 } 32 33 void rorate(int& x,int d) 34 { 35 int y = tr[x].c[d^1]; tr[x].c[d^1] = tr[y].c[d], tr[y].c[d] = x; 36 maintain(x), maintain(y); x = y; 37 } 38 39 void insert(int &k,int x) 40 { 41 if( !k ){ 42 k = ++cnt; 43 tr[k].v = x, tr[k].c[0] = tr[k].c[1] = 0, tr[k].s = 1, tr[k].rd = rand(); 44 return; 45 } 46 tr[k].s++; 47 if( tr[k].v < x ){ 48 insert(tr[k].c[1],x); 49 if( tr[rc].rd > tr[k].rd ) rorate(k,0); 50 } 51 else { 52 insert(lc,x); 53 if( tr[lc].rd > tr[k].rd ) rorate(k,1); 54 } 55 } 56 57 int del(int &k,int x) 58 { 59 if( !k ) return 0; int t = 0; 60 if( tr[k].v < x ){ 61 t = tr[lc].s + 1; k = rc; return t + del(k,x); 62 } 63 else { 64 t = del(lc,x); tr[k].s -= t; return t; 65 } 66 } 67 68 int query_num(int k,int x) 69 { 70 if( tr[rc].s >= x ) return query_num(rc,x); 71 else if( tr[rc].s + 1 < x ) return query_num(lc,x-tr[rc].s-1); 72 else return tr[k].v; 73 } 74 75 int tmp = 0, tot, n, m, root = 0; 76 77 void out(int k) 78 { 79 if( lc ) out(lc); 80 cout<<tr[k].v<<" "<<tr[k].v + tmp<<endl; 81 if( rc ) out(rc); 82 } 83 84 int main() 85 { 86 n = read(), m = read(); char c[5]; 87 while(n--){ 88 scanf("%s", c); int x = read(); 89 if( c[0] == 'I' ) { 90 if( x >= m ) 91 insert(root,x-tmp); 92 } 93 if( c[0] == 'A' ) tmp += x; 94 if( c[0] == 'S' ) { 95 tmp -= x; 96 tot += del(root,m-tmp); 97 } 98 if( c[0] == 'F' ){ 99 if( tr[root].s < x ) printf("%d\n", -1); 100 else printf("%d\n", query_num(root,x)+tmp); 101 } 102 //cout<<endl; 103 //out(root); 104 } 105 cout<<tot<<endl; 106 return 0; 107 }
————————————————