【BZOJ1503】 [NOI2004]郁闷的出纳员 splay

splay模板题,都快把我做忧郁了。

由于自己调两个坑点。

1.删除时及时updata

2.Kth 考虑k满足该点的条件即r->ch[1]->size+1<=k && r->ch[1]->size+r->num>=k

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 using namespace std;
  5 struct SplayNode
  6 {
  7     SplayNode *fa,*ch[2];
  8     SplayNode();
  9     int data,size,num;
 10     int chr() {return this==fa->ch[1];}
 11     void updata() { size=ch[0]->size+ch[1]->size+num;}
 12 }*null;
 13 SplayNode::SplayNode() {fa=ch[0]=ch[1]=null; num=1; size=0;}
 14 int n,minn;
 15 inline int read() {int ans=0; char c; while ((c=getchar())==' ' || c=='\r' || c=='\n'); ans=c-'0'; while (isdigit(c=getchar())) ans=ans*10+c-'0'; return ans;}
 16 namespace Splay
 17 {
 18     SplayNode *Root;
 19     void MakeTree()
 20     {
 21         null=new SplayNode;
 22         *null=SplayNode();
 23         Root=null;
 24     }
 25     void rotate(SplayNode *x)
 26     {
 27         SplayNode *r=x->fa;
 28         if (x==null || r==null) return;
 29         int t=x->chr();
 30         r->ch[t]=x->ch[t^1];
 31         r->ch[t]->fa=r;
 32         if (r->fa==null) Root=x;
 33         else r->fa->ch[r->chr()]=x;
 34         x->fa=r->fa;
 35         x->ch[t^1]=r;
 36         r->fa=x;
 37         r->updata();
 38         x->updata();
 39     }
 40     void splay(SplayNode *x,SplayNode *y)
 41     {
 42         for (;x->fa!=y;rotate(x))
 43             if (x->fa->fa!=y)
 44                 if (x->chr()==x->fa->chr()) rotate(x->fa);
 45                 else rotate(x);
 46     }
 47     void insert(int v)
 48     {
 49         SplayNode *r=Root;
 50         if (Root==null)
 51         {
 52             Root=new SplayNode;
 53             Root->data=v;
 54             Root->updata();
 55             return;
 56         }
 57         if (Root->data==v)
 58         {
 59             Root->num++;
 60             Root->updata();
 61             return;
 62         }
 63         while (r->ch[r->data<v]!=null)
 64         {
 65             r=r->ch[r->data<v];
 66             if (r->data==v)
 67             {
 68                 r->num++;
 69                 splay(r,null);
 70                 return;
 71             }
 72         }
 73         r->ch[r->data<v]=new SplayNode;
 74         r->ch[r->data<v]->data=v;
 75         r->ch[r->data<v]->fa=r;
 76         splay(r->ch[r->data<v],null);
 77     }
 78     void pre(SplayNode *x,int v,SplayNode *&ans)
 79     {
 80         if (x==null) return;
 81         else if (x->data<v)
 82         {
 83             if (ans->data<x->data || ans==null) ans=x;
 84             pre(x->ch[1],v,ans);    
 85         }else pre(x->ch[0],v,ans);
 86     }
 87     void suc(SplayNode *x,int v,SplayNode *&ans)
 88     {
 89         if (x==null) return;
 90         else if (x->data>v)
 91         {
 92             if (ans->data>x->data || ans==null) ans=x;
 93             suc(x->ch[0],v,ans);
 94         }else suc(x->ch[1],v,ans);
 95     }
 96     void del(int v)
 97     {
 98         SplayNode *q=null; pre(Root,v,q);
 99         SplayNode *p=null; suc(Root,v,p);
100         if (q==null && p==null)
101         {
102             if (Root->num==1) Root=null;
103             else Root->num--,Root->updata();
104             return;
105         }
106         if (q==null)
107         {
108             splay(p,null);
109             if (p->ch[0]->num==1) p->ch[0]=null,p->updata();
110             else p->ch[0]->num--,splay(p->ch[0],null);
111             return;
112         }
113         if (p==null)
114         {
115             splay(q,null);
116             if (q->ch[1]->num==1) p->ch[1]=null,p->updata();
117             else p->ch[1]->num--,splay(p->ch[0],null);
118             return;
119         }
120         splay(q,null);
121         splay(p,q);
122         if (p->ch[0]->num==1) p->ch[0]=null,p->updata();
123         else p->ch[0]->num--,splay(p->ch[0],null);
124         return;
125     }
126     SplayNode *Kth(int k)
127     {
128         SplayNode *r=Root;
129         while (r!=null)
130         {
131             if (k<=r->ch[1]->size) r=r->ch[1];
132             else if (r->ch[1]->size+1<=k && r->ch[1]->size+r->num>=k) return r;
133             else 
134             {
135                 k-=r->ch[1]->size+r->num;
136                 r=r->ch[0];
137             }
138         }
139         return r;
140     }
141     SplayNode *find(int v)
142     {
143         SplayNode *r=Root;
144         while (r!=null)
145         {
146             if (r->data==v)
147             {
148                 splay(r,null);
149                 return r;
150             }
151             r=r->ch[r->data<v];
152         }
153         return null;
154     }
155 }
156 int main()
157 {
158     //freopen("1503.out","w",stdout);
159     int ans=0,dell=0,ans1=0;
160     Splay::MakeTree();
161     n=read(); minn=read();
162     while (n--)
163     {
164         char s[6];
165         int x;
166         scanf("%s",s); x=read();
167         if (s[0]=='I') if (x>=minn) Splay::insert(x-dell),ans++;
168         if (s[0]=='A') dell+=x;
169         if (s[0]=='S') 
170         {
171             dell-=x;
172             Splay::insert(minn-dell);
173             SplayNode *r=Splay::find(minn-dell);
174         //    Splay::splay(r,null);
175             if   (r->ch[0]!=null) ans1+=r->ch[0]->size,ans-=r->ch[0]->size;
176             while (r->ch[0]!=null)
177             {
178                 Splay::del(r->ch[0]->data);
179                 Splay::splay(r,null);
180             }
181             Splay::del(minn-dell);
182         }
183         if (s[0]=='F') 
184         if (x>ans) puts("-1");
185         else
186         printf("%d\n",Splay::Kth(x)->data+dell);
187     }
188     printf("%d\n",ans1);
189     return 0;
190 }
View Code


Description

OIER公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新建一个工资档案。老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第k多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧?

Input

Output

输出文件的行数为F命令的条数加一。对于每条F命令,你的程序要输出一行,仅包含一个整数,为当前工资第k多的员工所拿的工资数,如果k大于目前员工的数目,则输出-1。输出文件的最后一行包含一个整数,为离开公司的员工的总数。

Sample Input

9 10
I 60
I 70
S 50
F 2
I 30
S 15
A 5
F 1
F 2

Sample Output

10
20
-1
2

HINT

 

I命令的条数不超过100000 A命令和S命令的总条数不超过100 F命令的条数不超过100000 每次工资调整的调整量不超过1000 新员工的工资不超过100000

 

Source

 

 
—Anime Otaku Save The World.
posted @ 2016-03-21 20:51  DMoon  阅读(207)  评论(0编辑  收藏  举报