真*郁闷的出纳员

码题过程极其曲折艰难,硬是熬了两天,问了N个大神无数次,说起来都是泪,这是我A的第一道NOI的题目,同样第一次编splay的模板题

感觉以后不会再忘了,吓得我思路都清晰了,不愧我debug数个小时,诶终于......这是一个有血有泪的教训啊 ,在没理清思路之前不要码题啊,果然如某m性选手所说think twice,code once哦,真的是这样啊

原来splay的insert和rorate那里写的很差,然后被说了之后就改了过来,后期调试很要命啊

这道题有几个坑点,就是 没有人的时候加减不算,工资相同也是可以排名不同的 。 

?:好像不能乱用啊 

T,WA了很久。

总之非常坑,好多细节要注意 

 

#include<cstdio>

#include<cstring>
#include<algorithm>
#include<time.h>
using namespace std;
#define maxn 100010
int minn=999999,minsalary=0,n,counting=0;

int fa[maxn],son[maxn][2],siz[maxn],key[maxn],chohe[maxn];

int root,people=0,leave=0,tip=0;
void clear()
{
memset(fa,0,sizeof(int));
memset(son,0,sizeof(int));
memset(siz,0,sizeof(int));
memset(key,0,sizeof(int));
memset(chohe,0,sizeof(int));
}
int askflag(int now)
{
if(now==son[fa[now]][0]) return 0;
return 1;
}
void updata(int now)
{siz[now]=1+siz[son[now][0]]+siz[son[now][1]]+chohe[now];}
void rorate(int now)
{
    int flag=askflag(now),f=fa[now];
    if(f!=root) son[fa[fa[now]]][askflag(f)]=now,fa[now]=fa[f];
    else root=now,fa[now]=-1;
    if(son[now][!flag])fa[son[now][!flag]]=f;
    son[f][flag]=son[now][!flag];
    son[now][!flag]=f;
    fa[f]=now;
  updata(f); updata(now);
}
void splay(int now)
{
while(root!=now)
{
if(fa[now]!=root&&fa[fa[now]]!=now)
if(askflag(fa[now])!=askflag(now)) rorate(fa[now]);
else rorate(now);
rorate(now);
}
}
int Kth(int now,int k)
{
if(siz[son[now][0]]+1<=k&&k<=siz[son[now][0]]+1+chohe[now]) return now;
else if(siz[son[now][0]]+1>k&&son[now][0]) return Kth(son[now][0],k);
  else if(son[now][1]&&siz[son[now][0]]+1+chohe[now]<k) 
  return Kth(son[now][1],k-(siz[son[now][0]]+1+chohe[now]));
return -1;
}
int getpos(int now,int val)
{
if(val<key[now]&&siz[son[now][0]]) return getpos(son[now][0],val);
if(val>key[now]&&siz[son[now][1]]) return getpos(son[now][1],val);
return now;
}
void insert(int now)
{
int pos=getpos(root,key[now]);
if(pos==root&&!siz[root])
{
fa[root]=-1;
root=now;
updata(now);
}
else if(key[pos]!=key[now])
{
fa[now]=pos;
if(key[now]<key[pos])son[pos][0]=now;
if(key[now]>key[pos])son[pos][1]=now;
updata(now),updata(pos);
splay(now);
}
else
{
key[tip--]=0; 
chohe[pos]++;
updata(pos),updata(fa[pos]);
splay(pos);
}
}
void newnode(int x)
{
if(x<minsalary) return;
key[++tip]=x-counting;
if(!people) root=tip;
insert(tip);
people++;
if(x-counting<minn) minn=x-counting;
}
int find(int l,int r)
{
while(l<r&&l!=r)
{
int mid=(l+r)>>1;
int temp=key[Kth(root,mid)];
if(temp+counting>=minsalary) r=mid; 
if(temp+counting<minsalary) l=mid+1;
}
return Kth(root,(l+r)>>1);
}
void slash(int x)
{
counting-=x;
if(minn+counting>=minsalary) return;
int temp=find(1,people);
minn=key[temp];
splay(temp);
leave+=siz[son[root][0]];
people-=siz[son[root][0]];
son[root][0]=0;
siz[son[root][0]]=0;
if(minn+counting<minsalary)

leave+=(chohe[temp]+1),people-=(chohe[temp]+1); 

if(!people) counting=0;
else updata(temp);
}
void printff()
{
printf("("); 
for(int i=1;i<=tip;i++)
if(siz[i])  printf("%d ",key[i]+counting);
printf(")min is %d and counting is %d \n",minn+counting,counting);
}
void printfff()
{
printf("father :");
for(int i=1;i<=n;i++) printf("%d ",fa[i]);
printf("\nson ");
for(int i=1;i<=n;i++) printf("%d:(%d,%d) ",i,son[i][0],son[i][1]);
printf("\n");
}
int main()
{
int temp,t;
char c[10],kk;
scanf("%d%d",&n,&minsalary);
for(int i=1;i<=n;i++)
{
scanf("%s%d",c,&temp);
kk=c[0];
if(kk=='I') newnode(temp);
if(kk=='A'&&people) counting+=temp;
if(kk=='S'&&people) slash(temp);
if(kk=='F') 
{
int t=Kth(root,people-temp+1);
if(t!=-1)
printf("%d\n",key[t]+counting),splay(t);
else 
printf("-1\n");
}
}
printf("%d\n",leave);
return 0;
}

转载于:https://www.cnblogs.com/OcahIBye/p/6697180.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值