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

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

虽然是平衡树裸题,但一直TLE,只好改了insert和move的写法...

本来想着每次降工资就把工资-det加进去,转到根节点,然后把小于它的都删掉,再把它也删掉这样...

而且连insert都会TLE...是因为需要每次把新加入的点旋转到根...

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const maxn=100005;
int n,mn,det,val[maxn],siz[maxn],num[maxn],c[maxn][3],fa[maxn],nd=1,rt,lv;
//void pushup(int x){siz[x]=siz[c[x][0]]+siz[c[x][1]]+num[x];}
void pushup(int x){siz[x]=siz[c[x][0]]+siz[c[x][1]]+1;}
//void insert(int x,int v)
//{
//    if(!rt){rt=1;val[1]=v;num[1]=1;siz[1]=1;return;}
////    if(val[x]==v){num[x]++;siz[x]++;pushup(fa[x]);}
//    if(val[x]>v)
//    {
//        if(c[x][0])insert(c[x][0],v);
//        else c[x][0]=++nd,val[nd]=v,num[nd]=1,siz[nd]=1,fa[nd]=x;
//        pushup(x);return;
//    }
////    if(val[x]<v)
//    else
//    {
//        if(c[x][1])insert(c[x][1],v);
//        else c[x][1]=++nd,val[nd]=v,num[nd]=1,siz[nd]=1,fa[nd]=x;
//        pushup(x);return;
//    }
//}
int find(int x,int v)
{
    if(val[x]==v)return x;
    return find(c[x][val[x]<v],v);
}
void rotate(int x,int &k)
{
    int y=fa[x],z=fa[y],d=(c[y][1]==x);
    if(y==k)k=x;
    else c[z][c[z][1]==y]=x;
    fa[x]=z; fa[y]=x; fa[c[x][d^1]]=y;
    c[y][d]=c[x][d^1]; c[x][d^1]=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(int &k,int x,int Last)
{
    if(!k)
    {
        k=++nd;fa[k]=Last;siz[k]=1;
        val[k]=x;splay(k,rt);// 
        return;
    }
    if(x<val[k]) Insert(c[k][0],x,k);
    else Insert(c[k][1],x,k);
}
//void move()
//{
//    insert(rt,mn-det);int x=find(rt,mn-det);
//    splay(x,rt);lv+=siz[c[rt][0]];
//    if(num[rt]==1)
//    {
//        splay(c[rt][1],rt);
//        int y=c[rt][0];c[rt][0]=0;fa[y]=0;siz[y]=0;
//    }
//    else {num[rt]--;siz[rt]--;}
//    pushup(rt);
//}
int move(int &k,int Last)
{
    if(!k) return 0;
    int rtn=0;
    if(val[k]+det<mn)
    {
        rtn=move(c[k][1],k)+siz[c[k][0]]+1;
        siz[c[k][1]]=siz[k]-rtn;
        k=c[k][1],fa[k]=Last;
    }
    else
    {
        rtn=move(c[k][0],k);
        siz[k]-=rtn;
    }
    return rtn;
}
int query(int x,int k)
{
    if(siz[c[x][0]]+1==k)return val[x];
    if(siz[c[x][0]]+1>k)return query(c[x][0],k);
    else return query(c[x][1],k-siz[c[x][0]]-1);
}
int main()
{
    scanf("%d%d",&n,&mn);
    char ch[3];
    for(int i=1,x;i<=n;i++)
    {
        scanf("%s%d",&ch,&x);
        if(ch[0]=='I')
        {
//            if(x<mn)lv++;
//            if(x>=mn)insert(rt,x-det);
            if(x>=mn)Insert(rt,x-det,0);
        }
        if(ch[0]=='A')det+=x;
//        if(ch[0]=='S')det-=x,move();
        if(ch[0]=='S')det-=x,lv+=move(rt,0);
        if(ch[0]=='F')
        {
            if(x>siz[rt])printf("-1\n");
            else printf("%d\n",query(rt,siz[rt]-x+1)+det);
        }
    }
    printf("%d",lv);
    return 0;
} 

 

posted @ 2018-06-12 14:41  Zinn  阅读(168)  评论(0编辑  收藏  举报