# 【BZOJ 1503】[NOI2004]郁闷的出纳员

【链接】 我是链接,点我呀:)
【题意】

【题解】

I 2000
delta = 100

(并且对于每个人都是如此

(把这个min-delta移动到根节点。

x-delta插入

x+delta始终是每个人的真实工资这一点很关键。
(很棒的ideal

【代码】

#include <cstdio>
#define which(x) (ch[fa[x]][1]==x)
using namespace std;

int n,mi,delta;

const int N = 1e5 + 200;

int m,fa[N], tot, ch[N][2], root, x, siz[N],value[N];

void push_up(int x)
{
siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
}

int Rank(int x, int k)
{
if (siz[ch[x][0]] >= k)
return Rank(ch[x][0], k);
else
if (k == siz[ch[x][0]] + 1)
return x;
else
return Rank(ch[x][1], k - siz[ch[x][0]] - 1);
}

void Rotate(int x)
{
int f = fa[x];
bool k = which(x);
ch[f][k] = ch[x][!k];
ch[x][!k] = f;
ch[fa[f]][which(f)] = x;
fa[ch[f][k]] = f;
fa[x] = fa[f];
fa[f] = x;
siz[x] = siz[f];
push_up(f);
}

void Splay(int x, int g)
{
while (fa[x] != g)
{
int f = fa[x];
if (fa[f] == g)
{
Rotate(x);
break;
}
if (which(x) ^ which(f))
Rotate(x);
else
Rotate(f);
Rotate(x);
}
if (!g) root = x;
}

void cr(int x,int num)
{
if (!x){
root = ++tot;
siz[tot] = 1;
value[tot] = num;
return;
}
if (ch[x][num>value[x]]==0){
ch[x][num>value[x]] = ++tot;
value[tot] = num;
fa[tot] = x;
siz[tot] = 1;
}else
cr(ch[x][num>value[x]],num);
push_up(x);
}

int main()
{
//freopen("D:\\rush.txt","r",stdin);
long long ans = 0;

scanf("%d%d",&n,&mi);
for (int i = 1;i <= n;i++){
int k;
char s[5];
scanf("%s",s);
if (s[0]=='I'){
scanf("%d",&k);
if (k<mi) continue;
cr(root,k-delta);
Splay(tot,0);
}else if (s[0]=='A'){
scanf("%d",&k);
delta+=k;
}else if (s[0]=='S'){
scanf("%d",&k);
delta-=k;
cr(root,mi-delta);
Splay(tot,0);
ans+=siz[ch[tot][0]];
root = ch[tot][1];
fa[root] = 0;
}else if (s[0]=='F'){
scanf("%d",&k);
if (k>siz[root]){
printf("%d\n",-1);
}else{
int x = Rank(root,siz[root]-k+1);
Splay(x,0);
printf("%d\n",value[x]+delta);
}
}
}
printf("%lld\n",ans);
return 0;
}


posted @ 2018-03-28 09:16  AWCXV  阅读(104)  评论(0编辑  收藏  举报