• P2234 [HNOI2002]营业额统计


    题目链接

    平衡树练手题,我们看它这个数列是动态插入的,所以自然而然就会想到用平衡树来维护。平衡树Splay推荐大家看这篇博客

    其实差的最小值只有可能是它与其前驱或后继之差,不然就没有更小的了。因为节点是动态插入的,根据Splay的性质,我们为保证复杂度,就会每次将操作节点旋到根,而他的前驱和后继必然就是之前插入过的数。最后将最小值求和即可。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=1e6+7;
    const int INF=0x7fffffff;
    int ch[maxn][2];
    int n,x;
    int rt,sz;
    int cnt[maxn],fa[maxn],size[maxn],key[maxn];
    int ans;
    void pushup(int x){
        size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x];
    }
    bool check(int x){
        return ch[fa[x]][1]==x;
    }
    void rotate(int x){
        int y=fa[x],z=fa[y],who=check(x);
        ch[y][who]=ch[x][who^1];
        fa[ch[y][who]]=y;
        ch[x][who^1]=y;
        fa[y]=x,fa[x]=z;
        if(z) ch[z][ch[z][1]==y]=x;
        pushup(y),pushup(x);
    }
    void splay(int x){
        for(int f;(f=fa[x]);rotate(x)){
            if(fa[f]) rotate((check(f)==check(x))?f:x);
        }
        rt=x;
    }
    void insert(int x){
        if(!rt){
            rt=++sz;
            size[sz]=cnt[sz]=1;
            key[sz]=x;
            return;
        }
        int now=rt,f=0;
        while(1){
            if(x==key[now]){
                cnt[now]++;
                pushup(f); 
                pushup(now);
                splay(now);
                return;
            }
            f=now,now=ch[now][x>key[now]];
            if(!now){
                sz++;
                size[sz]=cnt[sz]=1;
                fa[sz]=f;
                key[sz]=x;
                ch[f][x>key[f]]=sz;
                pushup(f);
                splay(sz);
                return;
            }
        }
    }
    int pre(){
        int now=ch[rt][0];
        if(now==0) return INF;
        while(ch[now][1]) now=ch[now][1];
        return key[now];
    }
    int nxt(){
        int now=ch[rt][1];
        if(now==0) return INF;
        while(ch[now][0]) now=ch[now][0];
        return key[now];
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&x);
            insert(x);
            if(i==1) ans+=x;
            else{
                if(cnt[rt]>1){
                    ans+=0;    
                } 
                else{
                    int ans1=abs(x-pre());
                    int ans2=abs(x-nxt());
                    ans+=min(ans1,ans2);
                }
            }
        }
        printf("%d
    ",ans);
        return 0;
    } 
    View Code
  • 相关阅读:
    为archlinux安装mplayer
    linux与windows的文本文件之间的转换
    有关git的换行符的处理问题
    让git忽略文件模式的改变
    linux更新系统之后,删除多余的开机启动项
    关于centos更新后virtualbox无法使用的问题
    SQL 中逻辑运算符的优先级
    archlinux安装输入法需要的包及archlinux无法使用输入法的解决
    从前有座山,山里有座庙
    批量修改照片名称的shell脚本
  • 原文地址:https://www.cnblogs.com/LJB666/p/11346793.html
Copyright © 2020-2023  润新知