【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的處理,勤更新

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章