【bzoj1503】[NOI2004]郁闷的出纳员

大名鼎鼎的平衡树模板题,话说我当初学平衡树的时候到底去干嘛了,这道题都没做= =。
这道题实际上区间操作蛮水的,因为全部都加减根本不用在树的两侧添加结点,所以直接根节点打标记就好了,每次减少工资的时候查询有没有员工离开了公司。
这个题有一个坑点就是如果工资一开始就少于K就不需要添加进去了,因为这个坑点这道题我调了好久.

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
//1.splay写的不熟练
//2.坑点,注意m以下的数直接不要插了
//3.注意对size的处理,勤更新 
using namespace std;
const int N=100010;
int n,m;
int sz,root;
int ch[N][2],fa[N],size[N],cnt[N],key[N],tag[N];
inline void clear(int x){size[x]=tag[x]=cnt[x]=ch[x][0]=ch[x][1]=fa[x]=key[x]=0;}
inline int get(int x){return ch[fa[x]][1]==x;}
void pushdown(int x)
{
    if (!x||tag[x]==0)return;
    if (ch[x][0])key[ch[x][0]]+=tag[x],tag[ch[x][0]]+=tag[x];
    if (ch[x][1])key[ch[x][1]]+=tag[x],tag[ch[x][1]]+=tag[x];
    tag[x]=0;
}
inline void updata(int x)
{
    if (!x)return;
    size[x]=cnt[x];
    if (ch[x][0])size[x]+=size[ch[x][0]];
    if (ch[x][1])size[x]+=size[ch[x][1]];
}
inline void rotate(int x)
{
    pushdown(fa[x]);pushdown(x);
    int old=fa[x],oldf=fa[old],which=get(x);
    ch[old][which]=ch[x][which^1],fa[ch[old][which]]=old;
    ch[x][which^1]=old;fa[old]=x;fa[x]=oldf;
    if (oldf)ch[oldf][ch[oldf][1]==old]=x;
    updata(old),updata(x);
}
inline void splay(int x)
{
    for(int old;(old=fa[x]);rotate(x))
    if (fa[old])rotate(get(old)==get(x)?old:x);
    root=x;
}
inline void insert(int x)
{   

    if (!root){root=++sz;size[sz]=cnt[sz]=1;tag[sz]=fa[sz]=ch[sz][0]=ch[sz][1]=0;key[sz]=x;return;} 
    int now=root,old=0;
    while(1)
    {
        pushdown(now);
        if (key[now]==x)
        {
            cnt[now]++;
            updata(now);
            updata(old);    
            splay(now);
            break;
        }
        old=now;
        now=ch[now][key[now]<x];
        if (now==0)
        {
            fa[++sz]=old;
            tag[sz]=ch[sz][0]=ch[sz][1]=0;
            ch[old][key[old]<x]=sz;
            cnt[sz]=size[sz]=1;
            key[sz]=x;updata(old);
            splay(sz);
            break;
        }
    }
}
inline int findpos(int x)
{
    int ans=0,now=root;
    while(1)
    {
        pushdown(now);
        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];
        }
    }
}
inline int findnth(int x)
{   
    if (x>size[root])return -1;
    int now=root;
    while(1)
    {
//      cout<<"now "<<now<<' '<<key[ch[now][0]]<<' '<<x<<size[ch[now][1]]<<' '<<cnt[now]<<endl;
        pushdown(now);
        if (ch[now][1]&&x<=size[ch[now][1]])now=ch[now][1];
        else 
        {
            int temp=(ch[now][1]?size[ch[now][1]]:0)+cnt[now];
            if (x<=temp)return key[now];
            x-=temp;now=ch[now][0];
        }
    }
}
inline int pre()
{
    int now=ch[root][0];
    while(ch[now][1])
    now=ch[now][1];
    return now;
}
inline void del(int x)
{
    findpos(x);
    if (cnt[root]>1){cnt[root]--;updata(root);return;}
    if (!ch[root][1]&&!ch[root][0]){clear(root);root=0;return;}
    if (!ch[root][0]){int oldroot=root;root=ch[root][1];fa[root]=0;clear(oldroot);updata(root);return;}
    if (!ch[root][1]){int oldroot=root;root=ch[root][0];fa[root]=0;clear(oldroot);updata(root);return;}
    int leftbig=pre(),oldroot=root;
    splay(leftbig);
    ch[root][1]=ch[oldroot][1];
    fa[ch[oldroot][1]]=root;
    clear(oldroot);
    updata(root);
    return;
}
inline void solve(int x)
{
    insert(x);
//  cout<<"solve root "<<root<<endl;
//  for (int i=1;i<=sz;++i)
//  printf("%d %d %d %d %d %d\n",i,key[i],fa[i],ch[i][0],ch[i][1],tag[i]);
    clear(ch[root][0]);
    ch[root][0]=0;
    updata(root);
    del(x);
}
int add(int d)
{
    key[root]+=d;
    tag[root]+=d;
    pushdown(root);
    updata(root);
}
int main()
{
//  freopen("std.in","r",stdin);
//  freopen("std.out","w",stdout);
    char s[3];
    int qx;
    int tot=0,k=0;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;++i)
    {
        scanf("%s",s);
        scanf("%d",&qx);
        if (s[0]=='I'&&qx>=m)insert(qx),tot++;
        else if (s[0]=='A')add(qx);
        else if (s[0]=='S')add(-qx),solve(m),k++;
        else if (s[0]=='F')printf("%d\n",findnth(qx));
    }
    printf("%d",tot-size[root]);
    return 0;
}

1.splay写的不熟练
2.坑点,注意m以下的数直接不要插了
3.注意对size的处理,勤更新

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值