zoukankan      html  css  js  c++  java
  • HYSBZ1588 营业额统计【Splay】

    转载请注明出处,谢谢:http://www.cnblogs.com/KirisameMarisa/p/4366582.html   ---by 墨染之樱花

    【题目链接】http://www.lydsy.com/JudgeOnline/problem.php?id=1588

    【题目描述】逐个将数插入序列,定义最小波动为某个数与其之前的小于等于它的最大数与大于等于它的最小数和它的差值的较小值,求整个序列的最小波动之和。

    【思路】经典的不能再经典的平衡树题目,可用于测试各种平衡树模板。今天刚写了一棵自己风格的splay,用这道题测试一下,156ms效果还不错

    /* ***********************************************
    Author        :Kirisame_Marisa
    blog          :http://www.cnblogs.com/KirisameMarisa/
    Created Time  :2015年03月24日 星期二 20时45分12秒
    File Name     :splay.cpp
    ************************************************ */
    
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <ctime>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <map>
    #include <string>
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int MAXN=100010;
    #define eps 1e-10
    #define zero(x) (fabs(x)<eps)
    #define REP(X,N) for(int X=0;X<N;X++)
    #define REP2(X,L,R) for(int X=L;X<=R;X++)
    #define CLR(A,X) memset(A,X,sizeof(A))
    #define PB(X) push_back(X)
    #define MP(X,Y) make_pair(X,Y)
    #define IT iterator
    #define test puts("OK")
    typedef long long ll;
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    typedef vector<PII> VII;
    
    const int null=-1;
    
    struct node
    {
        int par;
        int cld[2];    //0是左儿子,1是右儿子
        int key;
    } ts[MAXN];
    int root,cnt;
    
    void init()
    {
        root=null;
        cnt=0;
    }
    
    int newnode(int p,int k)
    {
        ts[cnt].key=k;
        ts[cnt].par=p;
        ts[cnt].cld[0]=ts[cnt].cld[1]=null;
        return cnt++;
    }
    
    void rotate(int x,int k)    //k=0为左旋,k=1为右旋
    {
        int y=ts[x].par;
        ts[y].cld[!k]=ts[x].cld[k];
        if(ts[x].cld[k]!=null)
            ts[ts[x].cld[k]].par=y;
        ts[x].par=ts[y].par;
        if(ts[y].par!=null)
        {
            if(y==ts[ts[y].par].cld[0])
                ts[ts[y].par].cld[0]=x;
            else
                ts[ts[y].par].cld[1]=x;
        }
        ts[y].par=x;
        ts[x].cld[k]=y;
    }
    
    void splay(int x,int S)   //伸展操作,将x旋转到目标节点,其中S为目标节点的parent
    {
        while(ts[x].par!=S)
        {
            int p=ts[x].par;
            if(ts[p].par==S)
                rotate(x,ts[p].cld[0]==x);
            else
            {
                int d=(ts[ts[p].par].cld[0]==p);
                if(ts[p].cld[d]==x)
                    rotate(x,!d),rotate(x,d);
                else
                    rotate(p,d),rotate(x,d);
            }
        }
        if(S==-1)
            root=x;
    }
    
    bool insert(int x)
    {
        if(root==null)
        {
            root=newnode(null,x);
            return 1;
        }
        int r=root,pre=null;
        while(r!=null)
        {
            if(ts[r].key==x)
            {
                splay(r,null);     //如果直接找到的话就不新建节点,直接splay
                return 0;
            }
            else
            {
                pre=r;
                r=ts[r].cld[ts[r].key<x];
            }
        }
        int &t=ts[pre].cld[ts[pre].key<x];
        t=newnode(pre,x);
        splay(t,null);
        return 1;
    }
    
    int getlow(int x)         //获取比它小的最大值。由于插入操作x已经被旋转到根节点,所以只要寻找左子树的最大值即可,下同
    {
        int d=ts[root].cld[0];
        if(d==null)
            return INF;
        while(ts[d].cld[1]!=null)
            d=ts[d].cld[1];
        return x-ts[d].key;
    }
    
    int getup(int x)          //获取比它大的最小值
    {
        int d=ts[root].cld[1];
        if(d==null)
            return INF;
        while(ts[d].cld[0]!=null)
            d=ts[d].cld[0];
        return ts[d].key-x;
    }
    
    void debug(int x)
    {
        int l=ts[x].cld[0],r=ts[x].cld[1];
        if(l!=null)
            debug(l);
        printf("id:%2d key:%2d par:%2d lcd:%2d rcd:%2d
    ",x,ts[x].key,ts[x].par,l,r);
        if(r!=null)
            debug(r);
    }
    
    int main()
    {
        //freopen("in","r",stdin);
        //freopen("out","w",stdout);
        init();
        int n,x,sum=0;
        scanf("%d%d",&n,&x);
        sum+=x;
        insert(x);
        REP(i,n-1)
        {
            x=0;
            scanf("%d",&x);
            bool temp=insert(x);
            if(temp)
                sum+=min(getlow(x),getup(x));
        }
        printf("%d
    ",sum);
        return 0;
    }
    代码君
  • 相关阅读:
    Android -- 在一个Activity开启另一个Activity 并 获取他的返回值。
    Android -- Activity的生命周期,Activity四种启动模式 Standard, SingleTop,SingleTask,SingleInstance
    Python3 如何优雅地使用正则表达式(详解七)
    Python3 如何优雅地使用正则表达式(详解六)
    Python3 如何优雅地使用正则表达式(详解五)
    Python3 如何优雅地使用正则表达式(详解四)
    Python3 如何优雅地使用正则表达式(详解三)
    Python3 如何优雅地使用正则表达式(详解一)
    Windows编程中的若干难点
    魔法方法:算术运算
  • 原文地址:https://www.cnblogs.com/KirisameMarisa/p/4366582.html
Copyright © 2011-2022 走看看