大视野 1503 郁闷的出纳员 Splay 初步

来源:互联网 发布:h5 js开发3d 编辑:程序博客网 时间:2024/04/30 19:36
//大视野 1503 郁闷的出纳员 Splay 初步////解题思路:////参照大牛的思路,将增删所有的部分用一个变量w表示//对于工资的加减就是对w的操作.插入的时候只要先减//去这个影响就ok了.然后就是裸的Splay啦,注意第k多//的意思是从大到小...好吧这里我傻逼了////感悟:////这道题坑爹的是就在于,我理解了思路,参照大神的模板//自己硬敲了一发,结果wa了十几发,找茬也找不出来什么//然后,自己将版主的代码一交,好家伙,跟我一样,顿时内//心,拔凉拔凉的,然后一直在思考,还是没有什么思路,看//着,另外一位大牛的思路,跟之前的一模一样,一个wa一//个ac,我还是挺纳闷儿的,哎,菜鸟的痛啊,自己还是要好//好理解,继续加油吧~~~~FIGHTING!!!#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#define rep(x,a,b,c) for(int x = a; x <= b; x += c)using namespace std;const int MAX_N = 311111;const int INF = 2e9 + 9;int N,M;int w;int ans;struct SplayTree{int ch[MAX_N][2];int val[MAX_N];int sum[MAX_N];int pre[MAX_N];int rt;int Siz;int cnt[MAX_N];inline void Push_up(int x){sum[x] = sum[ch[x][0]] + sum[ch[x][1]] + cnt[x];}inline void init(){Siz = 0;cnt[0] = 0;NewNode(0,rt,-INF);NewNode(rt,ch[rt][1],INF);sum[rt] = 2;}inline void NewNode(int y,int &x,int v){x = ++Siz;pre[x] = y;ch[x][0] = ch[x][1] = 0;val[x] = v;sum[x] = 1;cnt[x] = 1;}void Rotate(int x,int d){int y = pre[x];ch[y][d^1] = ch[x][d];pre[ch[x][d]] = y;pre[x] = pre[y];if (pre[y])ch[pre[y]][ch[pre[y]][1] == y] = x;ch[x][d] = y;pre[y] = x;Push_up(y);}void Splay(int x,int goal){while(pre[x] != goal){if (pre[pre[x]] == goal){if (ch[pre[x]][0] == x)Rotate(x,1);else Rotate(x,0);}else {int y = pre[x], z = pre[y];if (ch[z][0] == y){if (ch[y][0] == x){Rotate(y,1);Rotate(x,1);}else {Rotate(x,0);Rotate(x,1);}}else {if (ch[y][1] == x){Rotate(y,0);Rotate(x,0);}else {Rotate(x,1);Rotate(x,0);}}}}Push_up(x);if (goal == 0) rt = x; }//void Insert(int v){  // 这个不对,中间的更新没有保存下来//int x = rt;//while(ch[x][val[x] < v]){//if (v == val[x]){//cnt[x]++;//sum[x]++;//Splay(x,0);//Push_up(x);//return ;//}//x = ch[x][val[x] < v];//}//NewNode(x,ch[x][val[x] < v],v);//Splay(x,0);//Push_up(x);//}void Insert(int &x,int v,int f){if (!x){NewNode(f,x,v);Splay(x,0);return ;}if (v == val[x]){cnt[x]++;sum[x]++;Splay(x,0);return ;}else if (v < val[x]){Insert(ch[x][0],v,x);}else {Insert(ch[x][1],v,x);}Push_up(x);}int F_min(int v){int x = rt;int ans = INF;while(x){if (val[x] == v)return v;if (val[x] > v)ans = min(ans,val[x]);if (val[x] > v)x = ch[x][0];else x = ch[x][1];}return ans;}int F_root(int v){int x = rt;while(x){if (val[x] == v)return x;if (val[x] < v)x = ch[x][1];else x = ch[x][0];}return 0;}int DeleteSubTree(int a){int x = F_root(a);int res = 0;if (x){Splay(1,0); // 将负无穷转到根Splay(x,1); // 将x转到负无穷的下面,则x的左孩子就是可以删除的子树res = sum[ch[x][0]];ch[x][0] = 0;Splay(x,0);}return res;}int GetK(int x,int k){if (k < sum[ch[x][0]] + 1){return GetK(ch[x][0],k);}else if (k > sum[ch[x][0]] + cnt[x]){return GetK(ch[x][1],k-sum[ch[x][0]]-cnt[x]);}else {Splay(x,0);return val[x];}}}spt;void input(){char op[5];int x;w = 0;ans = 0;spt.init();rep(i,1,N,1){scanf("%s%d",op,&x);if (op[0] == 'I'){if (x >= M)spt.Insert(x-w);//spt.Insert(spt.rt,x-w,0);}else if (op[0] == 'S'){w-=x;//spt.DeleteTree(spt.rt,0);ans += spt.DeleteSubTree(spt.F_min(M-w));}else if (op[0] == 'A'){w+=x;}else {if (x+2>spt.sum[spt.rt]) puts("-1");else printf("%d\n",spt.GetK(spt.rt,spt.sum[spt.rt]-x)+w);}}printf("%d\n",ans);}int main(){//freopen("1.in","r",stdin);//freopen("1.out","w",stdout);scanf("%d%d",&N,&M);input();return 0;}

0 0
原创粉丝点击