【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 }



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

时间: 2024-10-12 21:12:37

【BZOJ1503】 [NOI2004]郁闷的出纳员 splay的相关文章

[BZOJ1503][NOI2004]郁闷的出纳员 无旋Treap

1503: [NOI2004]郁闷的出纳员 Time Limit: 5 Sec  Memory Limit: 64 MB Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反之,如果心情不好,就可能把他们的工资扣除一个相同的量.我真不知道除了调工资他还做什么其它事情.工资的频繁调

bzoj1503 [NOI2004]郁闷的出纳员(名次树+懒惰标记)

1503: [NOI2004]郁闷的出纳员 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 8705  Solved: 3027[Submit][Status][Discuss] Description OIER 公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是, 我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反

NOI2004 郁闷的出纳员 Splay

郁闷的出纳员 [问题描述] OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反之,如果心情不好,就可能把他们的工资扣除一个相同的量.我真不知道除了调工资他还做什么其它事情. 工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离

BZOJ1503 [NOI2004]郁闷的出纳员

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1503 [我的感受] 这题郁闷了很久,因为discuss里讨论的问题和我都不是一个问题... discuss里的当然是一大坑点啦,就是初始工资挂了的不算在最后踢出的人数中. 不过这个我倒是刚开始就这么打的...不过我一直超时啊超时啊... 终于要来了数据...额,原来是平衡树的性质都没怎么用...根本没转几次啊,然后数据就特意卡了这个,连续添加递增工资的人[变成了链] 那我就随机转一转好了

[BZOJ1503] [NOI2004] 郁闷的出纳员 (treap)

Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反之,如果心情不好,就可能把他们的工资扣除一个相同的量.我真不知道除了调工资他还做什么其它事情.工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司

BZOJ1503 NOI2004 郁闷的出纳员 平衡树

题意:开始时给定一个空的数列,要求维护:1.加入一个数  2.数列中所有元素+k  3.数列中所有元素-k  4.查询数列中的第k大.其中对于任意时刻,如果有一个元素<Min,则删除该元素. 题解:平衡树裸题……话说当年还打算把Splay Treap SBT都学一下,结果现在只会Splay了QAQ #include <cstdio> #include <cstring> #include <cstdlib> #include <climits> #in

BZOJ[NOI2004]郁闷的出纳员 | Splay板子题

题目: 洛谷也能评测....还有我wa了10多次的记录233 题解: 不要想得太复杂,搞一个全局变量记录一下工资的改变量Delta,这样可以等询问的时候就输出val+Delta,然后插入的时候插入x-Delta 不要想会不会有员工工资一样,直接插入就好,这样省不少代码量. 对于降工资操作,插入一个min-Delta节点,ans+=左子树大小,右儿子作为新的根节点 直接走的员工不要算ans #include<cstdio> #include<algorithm> #include&l

bzoj1503: [NOI2004]郁闷的出纳员 fhqtreap版

这道题写法和之前差不多 但是fhqtreap在加点的时候为了同时维护大根堆以及二叉排序树的性质所以插入时也要注意分裂 fhqteap需要判断指针是否为空 不然就会re 这个我调了很久 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int M=150000; int read(){ int ans=0,f=1,c=getchar(); while(c<

【权值分块】bzoj1503 [NOI2004]郁闷的出纳员

权值分块,离散化非常蛋疼,只能离散化搞…… 需要支持操作:删除<=某个值得所有权值==打标记 O(sqrt(n)) 码长和我的平衡树差不多……速度快3倍左右. 1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 #define N 201001 7 struct Point{int v,p;}tmp