• BZOJ1588 营业额统计 (Splay)


    营业额统计

    营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。

    Input

    第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数) ,表示第i天公司的营业额。

    Output

    输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。

    Sample Input
    	6
    5
    1
    2
    5
    4
    6 
    Sample Output
    	12
    此模板里的查前驱后继是正确的。
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <time.h>
    #include <string>
    #include <map>
    #include <stack>
    #include <vector>
    #include <set>
    #include <queue>
    #define maxn 102
    using namespace std;
    const int inf=0x3f3f3f3f;
    const int MAXN=2e5+100;
    int lim;
    struct SplayTree {
        int sz[MAXN];
        int ch[MAXN][2];
        int pre[MAXN];
        int rt,top;
        inline void up(int x) {
            sz[x]  = cnt[x]  + sz[ ch[x][0] ] + sz[ ch[x][1] ];
        }
        inline void Rotate(int x,int f) {
            int y=pre[x];
            ch[y][!f] = ch[x][f];
            pre[ ch[x][f] ] = y;
            pre[x] = pre[y];
            if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x;
            ch[x][f] = y;
            pre[y] = x;
            up(y);
        }
        inline void Splay(int x,int goal) { //将x旋转到goal的下面
            while(pre[x] != goal) {
                if(pre[pre[x]] == goal) Rotate(x, ch[pre[x]][0] == x);
                else   {
                    int y=pre[x],z=pre[y];
                    int f = (ch[z][0]==y);
                    if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f);
                    else Rotate(y,f),Rotate(x,f);
                }
            }
            up(x);
            if(goal==0) rt=x;
        }
        inline void RTO(int k,int goal) { //将第k位数旋转到goal的下面
            int x=rt;
            while(sz[ ch[x][0] ] != k-1) {
                if(k < sz[ ch[x][0] ]+1) x=ch[x][0];
                else {
                    k-=(sz[ ch[x][0] ]+1);
                    x = ch[x][1];
                }
            }
            Splay(x,goal);
        }
        inline void vist(int x) {
            if(x) {
                printf("结点%2d : 左儿子  %2d   右儿子  %2d   %2d sz=%d
    ",x,ch[x][0],ch[x][1],val[x],sz[x]);
                vist(ch[x][0]);
                vist(ch[x][1]);
            }
        }
        inline void Newnode(int &x,int c) {
            x=++top;
            ch[x][0] = ch[x][1] = pre[x] = 0;
            sz[x]=1;
            cnt[x]=1;
            val[x] = c;
        }
        inline void init() {
            sum=ch[0][0]=ch[0][1]=pre[0]=sz[0]=0;
            rt=top=0;
            cnt[0]=0;
            Newnode(rt,-inf);
            Newnode(ch[rt][1],inf);
            pre[top]=rt;
            sz[rt]=2;
        }
        inline void Insert(int &x,int key,int f) {
            if(!x) {
                Newnode(x,key);
                pre[x]=f;
                Splay(x,0);
                return ;
            }
            if(key==val[x]) {
                cnt[x]++;
                sz[x]++;
                Splay(x,0);
                return ;
            } else if(key<val[x]) {
                Insert(ch[x][0],key,x);
            } else {
                Insert(ch[x][1],key,x);
            }
            up(x);
        }
        //找前驱
        void findpre(int x,int key,int &ans){
            if(!x)  return ;
            if(val[x] <= key){
                ans=val[x];
                findpre(ch[x][1],key,ans);
            } else
                findpre(ch[x][0],key,ans);
        }
        void findsucc(int x,int key,int &ans){
            if(!x) return ;
            if(val[x]>=key) {
                ans=val[x];
                findsucc(ch[x][0],key,ans);
            } else
                findsucc(ch[x][1],key,ans);
        }
        void del(int &x,int f) {
            if(!x) return ;
            if(val[x]>=lim) {
                del(ch[x][0],x);
            } else {
                sum+=sz[ch[x][0]]+cnt[x];
                x=ch[x][1];
                pre[x]=f;
                if(f==0) rt=x;
                del(x,f);
            }
            if(x)  up(x);
        }
        inline void update() {
            del(rt,0);
        }
        inline int find_kth(int x,int k) {
            if(k<sz[ch[x][0]]+1) {
                return find_kth(ch[x][0],k);
            } else if(k > sz[ ch[x][0] ] + cnt[x] )
                return find_kth(ch[x][1],k-sz[ch[x][0]]-cnt[x]);
            else {
                Splay(x,0);
                return val[x];
            }
        }
        int cnt[MAXN];
        int val[MAXN];
        int sum;
    } spt;
    int main() {
        int n;
        scanf("%d",&n);
        spt.init();
        int ans=0,a;
        scanf("%d",&a);
        spt.Insert(spt.rt,a,0);
        ans=a;
        n--;
        while(n--){
            a=0;
            scanf("%d",&a);
            int x,y;
            spt.findpre(spt.rt,a,x);
            spt.findsucc(spt.rt,a,y);
            ans+=min(abs(a-x),abs(a-y));
            spt.Insert(spt.rt,a,0);
        }
        printf("%d
    ",ans);
        return 0;
    }

  • 相关阅读:
    通俗理解乐观锁和悲观锁
    面试系列-HashMap和Hashtable的区别
    单点登录原理与实现
    CodeReview常见代码问题
    漫画:什么是冒泡排序?
    Redis 和 Memcached 的区别
    动态图文了解 8 大排序算法
    分布式系统常见的事务处理机制
    面试系列-String,StringBuffer,StringBuilder三者区别
    面试系列-高并发之synchronized
  • 原文地址:https://www.cnblogs.com/jianrenfang/p/6275701.html
Copyright © 2020-2023  润新知