您的位置:首页 > 其它

[BZOJ1503][NOI2004]郁闷的出纳员(平衡树splay)

2017-03-08 14:43 423 查看
题目:

我是超链接

题解:

那什么.....今天真是有毒,splay都是细节没有考虑好,如果这个人本来就达不到minn,何必让他加入公司呢......

没有写区间操作,直接把minn处理了,好像简单一些呢

代码:

#include <cstdio>
#define N 100000
using namespace std;
int f[N+5],cnt[N+5],size[N+5],ch[N+5][2],key[N+5];
int sz=0,root=0,ff=0,e=0,tot;
void clear(int x){size[x]=cnt[x]=key[x]=f[x]=0;ch[x][0]=ch[x][1]=0;}
int get(int x){return ch[f[x]][1]==x;}
int pre()
{
int now=ch[root][0];
while (ch[now][1]) now=ch[now][1];
return now;
}
int next()
{
int now=ch[root][1];
while (ch[now][0]) now=ch[now][0];
return now;
}
void updata(int x)
{
if (x)
{
size[x]=cnt[x];
if (ch[x][0]) size[x]+=size[ch[x][0]];
if (ch[x][1]) size[x]+=size[ch[x][1]];
}
}
void rotate(int x) {
int old=f[x],oldf=f[old],which=get(x);
ch[old][which]=ch[x][which^1];
f[ch[x][which^1]]=old;
ch[x][which^1]=old;
f[old]=x;
f[x]=oldf;
if (oldf) ch[oldf][ch[oldf][1]==old]=x;
updata(old);
updata(x);
}
void splay(int x)
{
for (int fa;fa=f[x];rotate(x))
if (f[fa])
rotate((get(x)==get(fa))?fa:x);
root=x;
}
int findx(int x)
{
int now=root;
while (1)
{
if(ch[now][0] && x<=size[ch[now][0]])
now=ch[now][0];
else
{
int tmp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now];
if (x<=tmp) return key[now];
x-=tmp; now=ch[now][1];
}
}
}
int find(int x)
{
int ans=0,now=root;
while (1)
{
if (x<key[now])
now=ch[now][0];
else
{
ans+=(ch[now][0]?size[ch[now][0]]:0);
if (x==key[now])
{
splay(now); return ans+1;
}
ans+=cnt[now];
now=ch[now][1];
}
}
}
void insert(int x)
{
if (root==0)
{
sz++;root=sz;size[sz]=cnt[sz]=1;key[sz]=x;f[sz]=0;ch[sz][0]=ch[sz][1]=0;return;
}
int now=root,fa=0;
while (1)
{
if (x==key[now])
{
cnt[now]++; updata(now); updata(fa); splay(now); return;
}
fa=now;
now=ch[now][key[now]<x];
if (now==0)
{
sz++;
size[sz]=cnt[sz]=1;key[sz]=x;f[sz]=fa;ch[sz][0]=ch[sz][1]=0;
ch[fa][key[fa]<x]=sz;
updata(fa);
splay(sz);
return;
}
}
}
void del(int x)
{
int whatever=find(x);
if (cnt[root]>1)
{
cnt[root]--; updata(root); return;
}
if (!ch[root][0] && !ch[root][1]) {
clear(root); root=0; return;
}
if (!ch[root][0])
{
int oldroot=root; root=ch[root][1]; f[root]=0; clear(oldroot); return;
}
else if (!ch[root][1])
{
int oldroot=root; root=ch[root][0]; f[root]=0; clear(oldroot); return;
}
int leftbig=pre(),oldroot=root;
splay(leftbig);
f[ch[oldroot][1]]=root;
ch[root][1]=ch[oldroot][1];
clear(oldroot);
updata(root);
return;
}
int main()
{
int n,minn,i;
scanf("%d%d",&n,&minn);
for (i=1;i<=n;i++)
{
char chh;int x;
scanf("\n%c%d",&chh,&x);
switch(chh)
{
case 'I':if (x<minn) continue; insert(x-e); tot++; break;
case 'A':e+=x; break;
case 'S':e-=x; insert(minn-e); ff+=size[ch[root][0]]; ch[root][0]=0; del(minn-e); break;
case 'F':if (tot-ff<x) printf("-1\n");else printf("%d\n",findx(tot-ff-x+1)+e); break;
}
4000

}
printf("%d",ff);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: