【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();
162     while (n--)
163     {
164         char s[6];
165         int x;
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多的员工拿多少工资。每当这时，我就不得不对数万个员工进行一次漫长的排序，然后告诉他答案。好了，现在你已经对我的工作了解不少了。正如你猜的那样，我想请你编一个工资统计程序。怎么样，不是很困难吧？

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

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编辑  收藏  举报