您的位置:首页 > 其它

【平衡树】BZOJ1503(NOI2004)[郁闷的出纳员]题解

2017-06-30 08:28 501 查看

题目概述



ps:员工一旦发现自己的工资低于工资下界,就会离开公司,再也不会回来了。

解题报告

这道题有插入有删除且求第k大显然用平衡树做,只不过加工资和减工资不是很常规的操作。想一想可以发现加工资和减工资用Lazy-tag就可以解决,但是实际上并不需要,因为加工资和减工资表面看上去是员工工资的变化,实际上我们也可以看做是工资下界发生了变化!所以我们不用去调整每个员工的工资,只需要调整工资下界即可,但这样一来新员工的工资就不是读入的工资了,要加上当前工资下界MIN减去最初工资下界fst,同理,查询的答案也需要减去MIN-fst。

比较坑爹的是,新员工如果工资直接比工资下界低离开公司,是不算入离开人数的……

由于最近学了下SBT,于是SBT和Treap都抄板子打了一遍……

示例程序

Treap

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int MAXINT=((1<<30)-1)*2+1,maxn=100000;

int te,fst,MIN,ans;
struct Treap
{
Treap* son[2];int x,w,si,p;
Treap(int K,Treap* P,int S=1) {si=w=S;x=K;son[0]=son[1]=P;p=rand();}
int cmp(int k) {if (k<x) return 0;if (k==x) return -1;if (k>x) return 1;}
void Pushup() {si=son[0]->si+son[1]->si+w;}
};
Treap nil(0,&nil,0),*null=&nil,*ro=null;

void Rotate(Treap* &id,int d)
{
Treap* t=id->son[d^1];id->son[d^1]=t->son[d];t->son[d]=id;
id->Pushup();t->Pushup();id=t;
}
void Insert(Treap* &id,int x)
{
if (id==null) {id=new Treap(x,null);return;}
int d=id->cmp(x);
if (d==-1) id->w++; else
{
Insert(id->son[d],x);
if (id->son[d]->p>id->p) Rotate(id,d^1);
}
id->Pushup();
}
void Delete(Treap* &id,int x)
{
if (id==null) return;
int d=id->cmp(x);
if (d==-1)
{
if (id->w>1) id->w--; else
if (id->son[0]==null) id=id->son[1]; else
if (id->son[1]==null) id=id->son[0]; else
{
int son;if (id->son[0]->p>id->son[1]->p) son=0; else son=1;
Rotate(id,son^1);if (id==null) return;
Delete(id->son[son^1],x);
}
if (id==null) return;
} else Delete(id->son[d],x);
id->Pushup();
}
int getkth(Treap* id,int k)
{
if (id==null) return -1;
if (id->son[0]->si<k&&k<=id->son[0]->si+id->w) return id->x-MIN+fst; else
if (k<=id->son[0]->si) return getkth(id->son[0],k); else
return getkth(id->son[1],k-(id->son[0]->si+id->w));
}
int getpre(Treap* id,int k)
{
if (id==null) return -MAXINT;
int d=id->cmp(k);
if (d==1)
{
int now=id->x,tem=getpre(id->son[1],k);
if (tem!=-MAXINT) return tem; else return now;
} else return getpre(id->son[0],k);
}

char readc()
{
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
if (l==r) return EOF; else return *l++;
}
bool Eoln(char ch) {return ch==10||ch==13||ch==EOF;}
int readi(int &x)
{
int tot=0,f=1;char ch=readc(),lst=ch;
while ('9'<ch||ch<'0') {if (ch==EOF) return EOF;lst=ch;ch=readc();}
if (lst=='-') f=-f;
while ('0'<=ch&&ch<='9') tot=tot*10+ch-48,ch=readc();
x=tot*f;
return Eoln(ch);
}
char getrch() {char ch=readc();while ('Z'<ch||ch<'A') ch=readc();return ch;}
int main()
{
freopen("program.in","r",stdin);
freopen("program.out","w",stdout);
readi(te);readi(fst);MIN=fst;
while (te--)
{
int x;
switch(getrch())
{
case 'I':readi(x);if (x+MIN-fst>=MIN) Insert(ro,x+MIN-fst);break;
case 'A':readi(x);MIN-=x;break;
case 'S':readi(x);MIN+=x;break;
case 'F':readi(x);x=ro->si-x+1;printf("%d\n",getkth(ro,x));break;
}
for (int now=getpre(ro,MIN);now!=-MAXINT;now=getpre(ro,MIN))
Delete(ro,now),ans++;
}
printf("%d\n",ans);
return 0;
}


SBT

#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXINT=((1<<30)-1)*2+1;

int te,fst,MIN,ans;
struct node
{
node* son[2];int si,key;
node(int k,node* p,int s=1) {si=s;key=k;son[0]=son[1]=p;}
int cmp(int k) {return k>=key;}
void Pushup() {si=son[0]->si+1+son[1]->si;}
};
node nil(0,&nil,0);
typedef node* P_node;
P_node null=&nil,ro=null;
void Rotate(P_node &p,int d)
{
P_node t=p->son[d^1];p->son[d^1]=t->son[d];t->son[d]=p;
p->Pushup();t->Pushup();p=t;
}
void Maintain(P_node &p,bool fl)
{
P_node L=p->son[0],R=p->son[1];
if (!fl)
if (L->son[0]->si>R->si) Rotate(p,1); else
if (L->son[1]->si>R->si) Rotate(p->son[0],0),Rotate(p,1); else
return;
else
if (R->son[1]->si>L->si) Rotate(p,0); else
if (R->son[0]->si>L->si) Rotate(p->son[1],1),Rotate(p,0); else
return;
Maintain(p->son[0],0);Maintain(p->son[0],1);
Maintain(p->son[1],0);Maintain(p->son[1],1);
Maintain(p,0);Maintain(p,1);
}
void Insert(P_node &p,int k)
{
if (p==null) {p=new node(k,null);return;}
int d=p->cmp(k);Insert(p->son[d],k);
p->Pushup();Maintain(p,d);
}
int Delete(P_node &p,int k)
{
int d=p->cmp(k),now;
if (k==p->key||p->son[d]==null)
{
now=p->key;
if (p->son[0]==null) p=p->son[1]; else
if (p->son[1]==null) p=p->son[0]; else
p->key=Delete(p->son[0],p->key),p->Pushup(),Maintain(p,1);
return now;
}
now=Delete(p->son[d],k);
p->Pushup();Maintain(p,d^1);
return now;
}
int getkth(P_node p,int k)
{
if (p==null) return -1;
if (k==p->son[0]->si+1) return p->key+fst-MIN; else
if (k<=p->son[0]->si) return getkth(p->son[0],k); else
return getkth(p->son[1],k-p->son[0]->si-1);
}
int getpre(P_node p,int k)
{
if (p==null) return -MAXINT;
if (k>p->key) return max(p->key,getpre(p->son[1],k)); else
return getpre(p->son[0],k);
}

char readc()
{
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
if (l==r) return EOF; else return *l++;
}
bool Eoln(char ch) {return ch==10||ch==13||ch==EOF;}
int readi(int &x)
{
int tot=0,f=1;char ch=readc(),lst=ch;
while ('9'<ch||ch<'0') {if (ch==EOF) return EOF;lst=ch;ch=readc();}
if (lst=='-') f=-f;
while ('0'<=ch&&ch<='9') tot=tot*10+ch-48,ch=readc();
x=tot*f;
return Eoln(ch);
}
char getrch() {char ch=readc();while ('Z'<ch||ch<'A') ch=readc();return ch;}
int main()
{
freopen("program.in","r",stdin);
freopen("program.out","w",stdout);
readi(te);readi(fst);MIN=fst;
while (te--)
{
int x;
switch(getrch())
{
case 'I':readi(x);if (x+MIN-fst>=MIN) Insert(ro,x+MIN-fst);break;
case 'A':readi(x);MIN-=x;break;
case 'S':readi(x);MIN+=x;break;
case 'F':readi(x);x=ro->si-x+1;printf("%d\n",getkth(ro,x));break;
}
for (int now=getpre(ro,MIN);now!=-MAXINT;now=getpre(ro,MIN))
Delete(ro,now),ans++;
}
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: