BZOJ1503 [NOI2004]郁闷的出纳员
SPLAY题 4个操作
I 加入一个人,直接插就好了,////!!!!如果新来的人工资小于工资下界,那么他就会立刻离开,这个人是不加到最后离开公司人总数的,就是这里错了,一直找不到
A add 懒标记,在那些往下推的过程中pushdown一下,///这些过程例如说是,getk,Find,Ins等
S 这个减工资,先把这个sub+min插入到树里,然后放到根上,然后把左子树都删掉,再把加入的这个数删去,然后在add -k
F 查询第k大,查询第n-k+1小
//PS:最近写了不少这个,虽然神题没做几个,但是就先放一放了,该学点别的去了。
//几个splay注意的地方吧
//1、如果有重复权值的话,给每个点开一个cnt域把,cnt[x]表示,x这个节点 “里面”有几个值
//2、如果是维护序列的话,把下标当关键字插入就好,最好多加入两个节点,最前面一个,最后面一个,这样求前驱和后继就不用特判,很好用
//3、维护数列,建树的时候千万记得每次放入一个,更新root
//4、splay和rota可以模板,就是pushup改一下
//5、pushdown的话,就和线段树差不多啦
1 /************************************************************** 2 Problem: 1503 3 User: round_0 4 Language: C++ 5 Result: Accepted 6 Time:1164 ms 7 Memory:6820 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cstring> 12 #include <algorithm> 13 using namespace std; 14 typedef long long LL; 15 const int maxn = 220005; 16 int fa[maxn],son[2][maxn],val[maxn],siz[maxn],cnt[maxn],add[maxn]; 17 int tot,root,CNT; 18 void pushup(int x){ 19 siz[x] = siz[son[0][x]]+siz[son[1][x]]+cnt[x]; 20 } 21 void pushdown(int x){ 22 int l = son[0][x],r = son[1][x]; 23 if(add[x]){ 24 if(l)val[l]+=add[x]; 25 if(r)val[r]+=add[x]; 26 if(l)add[l]+=add[x]; 27 if(r)add[r]+=add[x]; 28 add[x] = 0; 29 } 30 } 31 void rota(int w,int x){ 32 int y = fa[x]; 33 son[!w][y] = son[w][x]; 34 if(son[w][x])fa[son[w][x]] = y; 35 fa[x] = fa[y]; 36 if(fa[y])son[y==son[1][fa[y]]][fa[y]] = x; 37 fa[y] = x; 38 son[w][x] = y; 39 pushup(y);pushup(x); 40 } 41 void splay(int x,int y){ 42 while(fa[x]!=y){ 43 if(fa[fa[x]]==y)rota(x==son[0][fa[x]],x); 44 else { 45 int w = fa[x]==son[0][fa[fa[x]]]; 46 if(x==son[w][fa[x]]){ 47 rota(!w,x);rota(w,x); 48 } 49 else { 50 rota(w,fa[x]);rota(w,x); 51 } 52 } 53 } 54 if(y==0)root = x; 55 } 56 void Ins(int v){ 57 int x = root; 58 while(1){ 59 pushdown(x); 60 siz[x]++; 61 if(v==val[x]){cnt[x]++;splay(x,0);return;} 62 if(v<val[x]){ 63 if(son[0][x])x = son[0][x]; 64 else break; 65 } 66 else { 67 if(son[1][x])x = son[1][x]; 68 else break; 69 } 70 } 71 fa[++tot] = x; 72 val[tot] = v; 73 siz[tot] = cnt[tot] = 1; 74 if(v<val[x])son[0][x] = tot;///here 75 else son[1][x] = tot; 76 splay(tot,0); 77 } 78 int getk(int k){ 79 int x = root; 80 while(1){ 81 pushdown(x); 82 if(k>siz[son[0][x]]&&k<=siz[son[0][x]]+cnt[x])return val[x]; 83 if(k<=siz[son[0][x]])x = son[0][x]; 84 else { 85 k-=(siz[son[0][x]]+cnt[x]); 86 x = son[1][x]; 87 } 88 } 89 } 90 int Find(int v){ 91 int x = root; 92 while(1){ 93 pushdown(x); 94 if(v==val[x])return x; 95 if(v<val[x])x = son[0][x]; 96 else x = son[1][x]; 97 } 98 } 99 void Del(int v){ 100 int x = Find(v); 101 splay(x,0); 102 if(cnt[x]>1){cnt[x]--;siz[x]--;return;} 103 int y = son[0][x],z = son[1][x]; 104 if(y==0&&z==0){root = 0;return;} 105 while(son[1][y])y = son[1][y]; 106 while(son[0][z])z = son[0][z]; 107 if(y)splay(y,0); 108 if(z)splay(z,y); 109 if(y==0){son[0][z] = 0;siz[z]--;return;} 110 if(z==0){son[1][y] = 0;siz[y]--;return;} 111 siz[z]--;siz[y]--;son[0][z] = 0; 112 } 113 int main() 114 { 115 // freopen("in.txt","r",stdin); 116 // freopen("out2.txt","w",stdout); 117 int n,m;scanf("%d%d",&n,&m); 118 char s[2];int k,ans = 0; 119 for(int i = 1;i<=n;++i){ 120 scanf("%s%d",s,&k); 121 if(s[0]=='I'){ 122 if(k<m){continue;} 123 if(CNT==0){ 124 root = ++tot; 125 siz[tot] = 1; 126 cnt[tot] = 1; 127 val[tot] = k; 128 } 129 else Ins(k); 130 CNT++; 131 } 132 else if(s[0]=='A'){ 133 if(CNT==0)continue; 134 add[root]+=k; 135 val[root]+=k; 136 } 137 else if(s[0]=='S'){ 138 if(CNT==0)continue; 139 Ins(m+k); 140 int t = siz[son[0][root]]; 141 son[0][root] = 0; 142 siz[root]-=t; 143 ans+=t; 144 CNT-=t; 145 Del(m+k); 146 add[root]-=k; 147 val[root]-=k; 148 } 149 else { 150 if(k>CNT)printf("-1\n"); 151 else printf("%d\n",getk(CNT-k+1)); 152 } 153 } 154 printf("%d\n",ans); 155 return 0; 156 }
弱者究竟为何而战?!