zoukankan      html  css  js  c++  java
  • 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
    ");
                else printf("%d
    ",query(rt,siz[rt]-x+1)+det);
            }
        }
        printf("%d",lv);
        return 0;
    } 
  • 相关阅读:
    oracle连接本地数据库
    ERWin 7.2下载安装及注册机
    关于oracle中to_char和to_date的用法
    2016年11月26号随笔(关于oracle数据库)
    SQL Server Browser服务的作用
    正则表达式
    server重启导致执行包的job运行失败
    Windows Log和SQL SERVER errorlog
    windows services创建和部署
    c# 读取App.config
  • 原文地址:https://www.cnblogs.com/Zinn/p/9172925.html
Copyright © 2011-2022 走看看