bzoj1503[NOI2004]郁闷的出纳员——Splay

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1503

好奇怪呀!为什么而TLE?

各种修改终于卡时过了。可是大家比我快多了呀?难道是因为自己把相同节点弄成一个节点、记了一个cnt的缘故?

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=1e5+5;
int n,c[N][2],fa[N],siz[N],cnt[N],ans,tot,rt;
ll lm,val[N],fx;
void pushup(int k){siz[k]=siz[c[k][0]]+siz[c[k][1]]+cnt[k];}
//void insert(int &k,int f,ll s)
//{
//  if(!k){k=++tot;siz[k]=1;cnt[k]=1;val[k]=s;fa[k]=f;return;}
//  if(s==val[k]){cnt[k]++;siz[k]++;return;}
//  int d=(s>val[k]);insert(c[k][d],k,s);
//  pushup(k);
//}
void rotate(int x,int &k)
{
    int y=fa[x],z=fa[y];
    if(y==k)k=x;
    else c[z][y==c[z][1]]=x;
    int d=(x==c[y][1]);
    fa[x]=z;fa[y]=x;fa[c[x][!d]]=y;//fa[x]=z在这里,不是43行 
    c[y][d]=c[x][!d];c[x][!d]=y;
    pushup(y);pushup(x);
}
void splay(int x,int &k)
{
    while(x!=k)
    {
        int y=fa[x],z=fa[y];
        if(y!=k)
        {
            if((c[y][0]==x)^(c[z][0]==y))rotate(x,k);
            else rotate(y,k);
        }
        rotate(x,k);
    }
}
void insert(ll s)
{
    if(!rt){rt=++tot;siz[rt]=1;cnt[rt]=1;val[rt]=s;fa[rt]=0;return;}
    int z,p=rt;
    while(p)
    {
        z=p;
        siz[p]++;
        if(s==val[p]){cnt[p]++;splay(p,rt);return;}//
        p=c[p][s>val[p]];
    }
    p=++tot;cnt[p]=1;siz[p]=1;val[p]=s;
    fa[p]=z;c[z][s>val[z]]=p;
    splay(p,rt);//
}
int find(int k,ll s)
{
    if(!k)return 0;
    if(val[k]==s)return k;
    int d=(s>val[k]);
    return find(c[k][d],s);
}
void del(ll s)
{
    int k=find(rt,s);if(!k)return;//
    if(k!=rt)splay(k,rt);
    ans+=siz[c[k][0]];
    if(cnt[k]==1)rt=c[k][1];
    else {
        cnt[k]--;fa[c[k][0]]=0;c[k][0]=0;pushup(k);
    }
}
ll query(int k,int s)
{
    if(siz[c[k][1]]<s&&siz[c[k][1]]+cnt[k]>=s)return val[k];
    if(siz[c[k][1]]>=s)return query(c[k][1],s);
    else return query(c[k][0],s-siz[c[k][1]]-cnt[k]);//
}
int main()
{
    scanf("%d%lld",&n,&lm);char ch;ll tp;
    while(n--)
    {
        cin>>ch;scanf("%lld",&tp);
        if(ch=='I')
        {
            if(tp-fx<lm)continue;
//          else insert(rt,0,tp-fx);
            else insert(tp-fx);
        }
        else if(ch=='A')fx+=tp,lm-=tp;
        else if(ch=='S')
        {
            fx-=tp;lm+=tp;
//          insert(rt,0,lm);
            insert(lm);del(lm);
        }
        else {
            if(tp>siz[rt])printf("-1\n");
            else printf("%lld\n",query(rt,tp)+fx);
        }
    }
    printf("%d",ans);
    return 0;
}
View Code
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=1e5+5;
int n,c[N][2],fa[N],siz[N],cnt[N],ans,tot,rt;
ll lm,val[N],fx;
void pushup(int k){siz[k]=siz[c[k][0]]+siz[c[k][1]]+cnt[k];}
//void insert(int &k,int f,ll s)
//{
//  if(!k){k=++tot;siz[k]=1;cnt[k]=1;val[k]=s;fa[k]=f;return;}
//  if(s==val[k]){cnt[k]++;siz[k]++;return;}
//  int d=(s>val[k]);insert(c[k][d],k,s);
//  pushup(k);
//}
void rotate(int x,int &k)
{
    int y=fa[x],z=fa[y];
    if(y==k)k=x;
    else c[z][y==c[z][1]]=x;
    int d=(x==c[y][1]);
    fa[x]=z;fa[y]=x;fa[c[x][!d]]=y;//fa[x]=z在这里,不是43行 
    c[y][d]=c[x][!d];c[x][!d]=y;
    pushup(y);pushup(x);
}
void splay(int x,int &k)
{
    while(x!=k)
    {
        int y=fa[x],z=fa[y];
        if(y!=k)
        {
            if((c[y][0]==x)^(c[z][0]==y))rotate(x,k);
            else rotate(y,k);
        }
        rotate(x,k);
    }
}
void insert(ll s)
{
    if(!rt){rt=++tot;siz[rt]=1;cnt[rt]=1;val[rt]=s;fa[rt]=0;return;}
    int z,p=rt;
    while(p)
    {
        z=p;
        siz[p]++;
        if(s==val[p]){cnt[p]++;splay(p,rt);return;}//
        p=c[p][s>val[p]];
    }
    p=++tot;cnt[p]=1;siz[p]=1;val[p]=s;
    fa[p]=z;c[z][s>val[z]]=p;
    splay(p,rt);//
}
//int find(int k,ll s)
//{
//  if(!k)return 0;
//  if(val[k]==s)return k;
//  int d=(s>val[k]);
//  return find(c[k][d],s);
//}
//void del(ll s)
//{
//  int k=find(rt,s);if(!k)return;//
//  if(k!=rt)splay(k,rt);
//  ans+=siz[c[k][0]];
//  if(cnt[k]==1)rt=c[k][1];
//  else {
//      cnt[k]--;fa[c[k][0]]=0;c[k][0]=0;pushup(k);
//  }
//}
int del(int &k,int f)
{
    if(!k)return 0;//
    int rtn=0;
    if(val[k]<lm||(val[k]==lm&&cnt[k]==1))
    {
        rtn=del(c[k][1],k)+siz[c[k][0]]+cnt[k];
        siz[c[k][1]]=siz[k]-rtn;
        k=c[k][1];fa[k]=f;
    }
    else{
        if(val[k]==lm)cnt[k]--,rtn++;
        rtn+=del(c[k][0],k);
        siz[k]-=rtn;
    }
    return rtn;
}
ll query(int k,int s)
{
    if(siz[c[k][1]]<s&&siz[c[k][1]]+cnt[k]>=s)return val[k];
    if(siz[c[k][1]]>=s)return query(c[k][1],s);
    else return query(c[k][0],s-siz[c[k][1]]-cnt[k]);//
}
int main()
{
    scanf("%d%lld",&n,&lm);char ch;ll tp;
    while(n--)
    {
        cin>>ch;scanf("%lld",&tp);
        if(ch=='I')
        {
            if(tp-fx<lm)continue;
//          else insert(rt,0,tp-fx);
            else insert(tp-fx);
        }
        else if(ch=='A')fx+=tp,lm-=tp;
        else if(ch=='S')
        {
            fx-=tp;lm+=tp;
//          insert(rt,0,lm);
            insert(lm);
            ans+=del(rt,0)-1;
        }
        else {
            if(tp>siz[rt])printf("-1\n");
            else printf("%lld\n",query(rt,tp)+fx);
        }
    }
    printf("%d",ans);
    return 0;
}
View Code

可以非递归地 insert。

这两个的del方式不同。

posted on 2018-06-12 17:06  Narh  阅读(131)  评论(0编辑  收藏  举报

导航