您的位置:首页 > 其它

BZOJ1503【NOI2004】郁闷的出纳员

2015-03-21 11:01 267 查看
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1503

【分析】

一段裸的splay,支持upper_bound,lower_bound,然后和线段树一样Lazy_Tag一下(代码写得太丑QAQ)。

注:如果加入的员工由于工资小于最低工资立刻离开了公司,此人不计入被炒员工总数(于是本题为我的AC率做出了巨大的贡献)

也可以不Lazy_Tag,这题可以在外面开一个tag记录当前全体员工加了多少工资(tag<0就是减了多少工资)。一个员工的工资就是他原来的工资加上tag,新加入的员工的“原来的工资”就是他的工资减tag。

【代码】

#include <cstdio>
using namespace std;

int n,min_salary,delete_num;

struct Node
{
Node *c[2];
int v,s,tag;
Node(){}
Node(Node *p) {v=p->v;s=1;tag=0;c[0]=c[1]=NULL;}
void Assign(int _v) {v=_v;}
int Child_Size(int o) {return (c[o]==NULL)?0:c[o]->s;}
void Update()
{
s=this->Child_Size(0)+this->Child_Size(1)+1;
if (c[0]!=NULL) c[0]->tag+=tag;
if (c[1]!=NULL) c[1]->tag+=tag;
v+=tag;tag=0;
}
int cmp(Node *p) {return p->v<v;}
int cmp(int k) {if (this->Child_Size(0)+1==k) return -1;return this->Child_Size(0)<k;}
};

struct Splay
{
Node *root,temp;
int k;

void Rotate(Node* &o,int d)
{
o->Update();
Node *p=o->c[d^1];
p->Update();
o->c[d^1]=p->c[d];
p->c[d]=o;
o->Update();p->Update();o=p;
}

void Splay_Node(Node* &o)
{
if (o==NULL) {o=new Node(&temp);return;}
o->Update();
int d=o->cmp(&temp);
Node *p=o->c[d];
if (p==NULL) {Splay_Node(o->c[d]);Rotate(o,d^1);return;}
p->Update();
int d2=p->cmp(&temp);
Splay_Node(p->c[d2]);
if (d==d2) Rotate(o,d^1);else Rotate(o->c[d],d2^1);
Rotate(o,d^1);
}

void Splay_Kth(Node* &o)
{
o->Update();
int d=o->cmp(k);
if (d==-1) return;
if (d) k-=o->Child_Size(0)+1;
Node *p=o->c[d];
p->Update();
int d2=p->cmp(k);
if (d2!=-1)
{
if (d2) k-=p->Child_Size(0)+1;
Splay_Kth(p->c[d2]);
if (d==d2) Rotate(o,d^1);else Rotate(o->c[d],d2^1);
}
Rotate(o,d^1);
}

void _Delete()
{
Node *l=root->c[0],*r=root->c[1];
delete root;root=NULL;
if (l==NULL && r==NULL) return;
else if (l!=NULL && r!=NULL) k=l->s,Splay_Kth(r),l->c[1]=r,root=l;
else root=(r==NULL)?l:r;
root->Update();
}

public:
void Delete()
{
while (k=(root==NULL)?0:root->s)
{
Splay_Kth(root);
if (root->v>=min_salary) break;
_Delete();
delete_num++;
}
}
void Insert(int _v) {temp.Assign(_v);Splay_Node(root);}
void Add_Salary(int _v) {if (root!=NULL) root->tag+=_v;}
void Salary_K(int _k)
{
k=_k;
if (root==NULL) printf("-1\n");
else if (root->s<k) printf("-1\n");
else Splay_Kth(root),printf("%d\n",(root->v<min_salary)?-1:root->v);
}
}T;

void Work()
{
char ch;
int x;
while ((ch=getchar())==' ' || ch=='\n');
scanf("%d",&x);
if (ch=='I') if (x>=min_salary) T.Insert(x);
if (ch=='A') T.Add_Salary(x);
if (ch=='S') T.Add_Salary(-x),T.Delete();
if (ch=='F') T.Salary_K(x);
}

int main()
{
scanf("%d%d",&n,&min_salary);
for (int i=1;i<=n;i++) Work();
printf("%d\n",delete_num);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: