【splay】【树状数组】 BZOJ 1503 [NOI2004]郁闷的出纳员

**************************************************************
    Problem: 1503
    User: 704035233
    Language: C++
    Result: Accepted
    Time:912 ms
    Memory:6348 kb
****************************************************************/
 
/*happywu
 * 2014.8.13
 * bzoj 1503 splay
 */
#include<cstdio>
#include<iostream>
#define Rep(i,n) for(int i=1;i<=n;i++)
using namespace std;
typedef long long LL;
const int MAX_N = 200010;
 
struct Node
{
    int key,num,Size,fa;
    int son[2];
}Tree[MAX_N];
int root=0,tot=0,n;

 
inline void Push_Down(int x)
{
   //此题无Push_Down操作
}
 
inline void Updata(int x)
{
    Tree[x].Size = Tree[Tree[x].son[0]].Size + Tree[Tree[x].son[1]].Size + Tree[x].num;
}
 
inline void Rotate(int x,int c){
    int y = Tree[x].fa;
    Push_Down(y);Push_Down(x);
    Tree[y].son[!c] = Tree[x].son[c];
    if(Tree[x].son[c])Tree[Tree[x].son[c]].fa = y;
    Tree[x].fa = Tree[y].fa;
    if(Tree[y].fa)
        Tree[Tree[y].fa].son[Tree[Tree[y].fa].son[1] == y] = x;
    Tree[x].son[c] = y; Tree[y].fa = x;
    Updata(y);Updata(x);
    if(Tree[x].fa == 0)root = x;
}
 
inline void Splay(int x,int f){
    Push_Down(x);
    while(Tree[x].fa != f)
    {
        if(Tree[Tree[x].fa].fa == f)
            Rotate(x,Tree[Tree[x].fa].son[0] == x);
        else
        {
            int y = Tree[x].fa;
            int kind = Tree[Tree[y].fa].son[1] == y;
            if(Tree[y].son[kind] == x)
                Rotate(y,!kind) , Rotate(x,!kind);
            else
                Rotate(x,kind)  , Rotate(x,!kind);
        }
    }
    if(f == 0)root = x;
    Updata(x);
}
 
inline void Insert(int val,int x){
    if(!x)
    {
        root = ++tot;
        Tree[tot].key = val; Tree[tot].fa = 0;Tree[tot].num = Tree[tot].Size = 1;
        return ;
    }
    if(Tree[x].key == val){
        Tree[x].num++;
        Tree[x].Size++;
        Updata(x);
        Splay(x,0);
        return ;
    }
    if(!Tree[x].son[val>Tree[x].key]){
        Tree[x].son[val>Tree[x].key] = ++tot;
        Tree[tot].fa = x;Tree[tot].key = val;Tree[tot].num = Tree[tot].Size = 1;
        Updata(x);
        Splay(tot,0);
        return ;
    }
    Insert(val, Tree[x].son[val>Tree[x].key]);
    Updata(x);
}
 
inline void Select(int k,int f)
{
    int tmp;
    int t = root;
    while(1)
    {
        Push_Down(t);
        tmp = Tree[Tree[t].son[0]].Size;
        if(tmp < k && k<= tmp+Tree[t].num)
            break;
        if(k<=tmp)
            t = Tree[t].son[0];
        else k -= tmp+Tree[t].num , t = Tree[t].son[1];
    }
    Splay(t,f);
}
 
inline void Traval(int x)
{
    Push_Down(x);
    if(Tree[x].son[0])Traval(Tree[x].son[0]);
    Rep(i,Tree[x].num) printf("%d ",Tree[x].key);
    if(Tree[x].son[1])Traval(Tree[x].son[1]);
}
 
int main()
{
     
    int n,val;
    LL m;
    char cnt;
    scanf("%d%lld",&n,&m);
    int d=0,ans=0;
    for(int i=1;i<=n;i++)
    {
 
        getchar();
        scanf("%c %d",&cnt,&val);
        if(cnt=='I' && val>=m)
            Insert(val-d,root);
        if(cnt=='A')d += val;
        if(cnt=='S')
        {
            Insert(m+val-d,root);
            d-=val;
            ans += Tree[Tree[root].son[0]].Size;
            if(Tree[root].num>1){
                Tree[root].num--;
                Tree[root].Size--;
                Tree[root].son[0] = 0;
                Updata(root);
            }
            else{
                root = Tree[root].son[1];
                Tree[root].fa = 0;
            }
        }
        if(cnt=='F')
        {
            if(val>Tree[root].Size)
                printf("%d\n",-1);
            else
            {
                Select(Tree[root].Size-val+1,0);
                printf("%d\n",Tree[root].key+d);
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

此题还可以用树状数组来实现 ,参考了WCMG 大神的代码

/**************************************************************
    Problem: 1503
    User: 704035233
    Language: C++
    Result: Accepted
    Time:308 ms
    Memory:3616 kb
****************************************************************/
 
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 300010;
int a[maxn+10],c[maxn+10];
int n,m,x,now,ans,add,delta;
char com;
inline int read(){
    static int r, sign;
    static char c;
    r = 0, sign = 1;
    do c = getchar(); while(c != '-' && (c < '0' || c > '9'));
    if( c == '-')sign = -1, c = getchar();
    while( c >= '0' && c <='9') r = r*10 +(int)(c - '0'), c = getchar();
    return sign * r;
}
void Add(int pos,int d)
{
 
    while(pos<=maxn){
        c[pos]+=d;
        pos+=(pos&(-pos));
    }
}
 
int find_kth(int x)
{
    if(x<1)return -1;
    int ans=0,cnt=0;
    for(int i=18;i>=0;i--)
    {
        ans+=(1<<i);
        if(ans>=maxn || cnt+c[ans]>=x)
            ans-=(1<<i);
        else cnt+=c[ans];
    }
    return ans+1+add-delta;
}
int main()
{
    scanf("%d%d",&n,&m);
    memset(a,0,sizeof(a));
    memset(c,0,sizeof(c));
    delta=10001;
    add=com=0;
    for(int i=1;i<=n;i++)
    {
        while(com!='I' && com !='A' && com!='S' && com != 'F')com=getchar();
        x=read();
        if(com=='I'&&x>=m){
            Add(delta+x-add,1);
            a[delta+x-add]++;
            now++;
        }
        if(com=='A')add+=x;
        if(com=='S'){
            for(int j=delta+m-add;j<delta+m+x-add;j++)
                if(j>0 && a[j]>0)
                {
                    Add(j,-a[j]);
                    ans+=a[j];
                    now-=a[j];
                    a[j]=0;
                }
            add-=x;
        }
        if(com=='F')
        {
            printf("%d\n",find_kth(now-x+1));
        }
        com=0;
    }
    printf("%d\n",ans);
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值