zoukankan      html  css  js  c++  java
  • 洛谷 P2234 [HNOI2002]营业额统计

    题目描述

    Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。

    Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:

    当最小波动值越大时,就说明营业情况越不稳定。

    而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。

    第一天的最小波动值为第一天的营业额。

    该天的最小波动值=min{|该天以前某一天的营业额-该天营业额|}。

    输入输出格式

    输入格式:

    输入由文件’turnover.in’读入。

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

    输出格式:

    ![https://cdn.luogu.org/upload/pic/1298.png]

    输入输出样例

    输入样例#1:

    6
    5
    1
    2
    5
    4
    6
    

    输出样例#1:

    12
    

    说明

    结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12

    思路:思路:题目说了这么多,实际上就两句最关键:第一天的最小波动值为第一天的营业额。该天的最小波动值=min{|该天以前某一天的营业额-该天营业额|}。对于第一天,直接加入答案中即可,之后的每天,因为求的是最小波动值,那么!!就是找插入这天营业额之前的这天营业额的前驱和后继呗,然后跟这个营业额做差取绝对值的最小值,但是有一点要注意,如果前驱为我们开始插入的-inf或后继为inf,则不能参与计算。

    代码:

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #include<cmath>
    #define maxn 32771
    #define inf 0x7fffffff
    using namespace std;
    int n,m,root,tot,a[maxn];
    inline int qread() {
      char c=getchar();int num=0,f=1;
      for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
      for(;isdigit(c);c=getchar()) num=num*10+c-'0';
      return num*f;
    }
    struct Tree {
      int fa,ch[2],siz,val,cnt; 
    }t[maxn];
    inline void pushup(int rt) {
      t[rt].siz=t[t[rt].ch[0]].siz+t[t[rt].ch[1]].siz+t[rt].cnt;
    }
    inline void rotate(int x) {
      int y=t[x].fa,z=t[y].fa;
      int k=t[y].ch[1]==x;
      t[z].ch[t[z].ch[1]==y]=x;
      t[x].fa=z;
      t[y].ch[k]=t[x].ch[k^1];
      t[t[x].ch[k^1]].fa=y;
      t[x].ch[k^1]=y,t[y].fa=x;
      pushup(y),pushup(x);
    }
    inline void splay(int x, int rt) {
      while(t[x].fa!=rt) {
        int y=t[x].fa,z=t[y].fa;
        if(z!=rt) (t[z].ch[0]==y)^(t[y].ch[0]==x)?rotate(x):rotate(y);
        rotate(x);
      }
      if(!rt) root=x;
    }
    inline void find(int x) {
      int u=root;
      if(!u) return;
      while(t[u].ch[x>t[u].val]&&x!=t[u].val) u=t[u].ch[x>t[u].val];
      splay(u,0);
    }
    inline void insert(int x) {
      int u=root,f=0;
      while(u&&t[u].val!=x) {
        f=u;
        u=t[u].ch[x>t[u].val];
      }
      if(u) t[u].cnt++;
      else {
        u=++tot;
        if(f) t[f].ch[x>t[f].val]=u;
        t[u].fa=f;t[u].val=x;
        t[u].ch[0]=t[u].ch[1]=0;
        t[u].cnt=t[u].siz=1;
      }
      splay(u,0);
    }
    inline int nxt(int x, int f) {
      find(x);
      int u=root;
      if(t[u].val>=x&&f) return u;
      if(t[u].val<=x&&!f) return u;
      u=t[u].ch[f];
      while(t[u].ch[f^1]) u=t[u].ch[f^1];
      return u; 
    }
    int main() {
      n=qread();
      insert(0x7fffffff),insert(-0x7fffffff);
      int ans=qread();
      insert(ans);
      for(int i=2,x;i<=n;++i) {
        x=qread();
        int minn=inf;
        if(t[nxt(x,0)].val!=-inf) minn=min(abs(t[nxt(x,0)].val-x),minn);
        if(t[nxt(x,1)].val!=inf) minn=min(abs(t[nxt(x,1)].val-x),minn);
        ans+=minn;
        insert(x);
      }
      printf("%d
    ",ans);
      return 0;
    }
    
  • 相关阅读:
    数论:扩展欧几里得算法
    数论:四大定理
    数论:完全数
    数论:求解不定方程和同余方程的实验范例
    Python记:列表和元组之序列相加
    动态规划入门:热血实战!
    Python记通用列表操作之切片!
    Python记:索引操作示例:将以数指定年,月,日的日期打印出来
    计算机的性能指标
    动态规划入门(2):01背包问题实践
  • 原文地址:https://www.cnblogs.com/grcyh/p/10569430.html
Copyright © 2011-2022 走看看