P2234 [HNOI2002]营业额统计
时间:2022-05-08
本文章向大家介绍P2234 [HNOI2002]营业额统计,主要内容包括题目描述、输入输出格式、输入输出样例、说明、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
题目描述
Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。
Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:
当最小波动值越大时,就说明营业情况越不稳定。
而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。
第一天的最小波动值为第一天的营业额。
输入输出格式
输入格式:
输入由文件’turnover.in’读入。
第一行为正整数n(n<=32767) ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数ai(|ai|<=1000000) ,表示第i天公司的营业额,可能存在负数。
输出格式:
输入输出样例
输入样例#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
这道题可以说是一道平衡树的水题,
但是在这里给出一道带权线段树的做法,
首先我们先将所有的点离散化一下,
然后考虑每一个点
我们需要在这个点的前面(也就是在比这个点小的所有点中)找一个最大的
再在这个点的后面(也就是比这个点小的所有点中)找一个最小的
那么把得到的这两个值分别与这个点的值做差,
再取最小值。
这个值就应该是答案
累加即可
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #include<cmath>
6 #include<cstdlib>
7 #define lli long long int
8 #define ls k<<1
9 #define rs k<<1|1
10 using namespace std;
11 const int MAXN=300001;
12 const int maxn=0x7fffff;
13 inline void read(int &n)
14 {
15 char c='+';int x=0;bool flag=0;
16 while(c<'0'||c>'9'){c=getchar();if(c=='-')flag=1;}
17 while(c>='0'&&c<='9'){x=x*10+c-48;c=getchar();}
18 flag==1?n=-x:n=x;
19 }
20 struct node
21 {
22 int l,r,mx,mn;
23 }tree[MAXN];
24 int a[MAXN];
25 int d[MAXN];
26 int hh=-1;
27 int kk=maxn;
28 struct lisan
29 {
30 int pos, va;
31 }data[MAXN];
32 inline int comp(const lisan &a,const lisan &b)
33 {
34 return a.va<b.va;
35 }
36 inline void update(int k)
37 {
38 tree[k].mn=min(tree[ls].mn,tree[rs].mn);
39 tree[k].mx=max(tree[ls].mx,tree[rs].mx);
40
41 }
42 inline void build(int ll,int rr,int k)
43 {
44 tree[k].l=ll;tree[k].r=rr;
45 if(tree[k].l==tree[k].r)
46 {
47 tree[k].mn=maxn;
48 tree[k].mx=-1;
49 return ;
50 }
51 int mid=(tree[k].l+tree[k].r)>>1;
52 build(ll,mid,ls);
53 build(mid+1,rr,rs);
54 update(k);
55 }
56 inline void query_max(int ll,int rr,int k)
57 {
58 if(ll<=tree[k].l&&tree[k].r<=rr)
59 {
60 if(tree[k].mn!=maxn)
61 hh=max(hh,tree[k].mx);
62 return ;
63 }
64 int mid=(tree[k].l+tree[k].r)>>1;
65 if(ll<=mid)
66 query_max(ll,rr,ls);
67 if(rr>mid)
68 query_max(ll,rr,rs );
69 update(k);
70 }
71 inline void query_min(int ll,int rr,int k)
72 {
73 if(ll<=tree[k].l&&tree[k].r<=rr)
74 {
75 if(tree[k].mx!=-1)
76 kk=min(kk,tree[k].mn);
77 return ;
78 }
79 int mid=(tree[k].l+tree[k].r)>>1;
80 if(ll<=mid)
81 query_min(ll,rr,ls);
82 if(rr>mid)
83 query_min(ll,rr,rs);
84 update(k);
85 }
86 void change(int k,int pos)
87 {
88 if(tree[k].l==tree[k].r)
89 {
90 tree[k].mx=tree[k].mn=tree[k].l;
91 return ;
92 }
93 int mid=(tree[k].l+tree[k].r)>>1;
94 if(pos<=mid)
95 change(ls,pos);
96 if(pos>mid)
97 change(rs,pos);
98 update(k);
99 }
100 int main()
101 {
102 //freopen("turnover.in","r",stdin);
103 //freopen("turnover.out","w",stdout);
104 int n;
105 read(n);
106 for(int i=1;i<=n;i++)
107 {
108 read(a[i]);
109 data[i].pos=i;
110 data[i].va=a[i];
111 }
112 sort(data+1,data+n+1,comp);
113 int tot=1;
114 a[data[1].pos]=tot;
115 d[1]=data[1].va;//离散化
116 for(int i=2;i<=n;i++)
117 {
118 if(data[i].va!=data[i-1].va)
119 tot++;
120 a[data[i].pos]=tot;
121 d[tot]=data[i].va;
122 }
123
124 build(1,tot,1);
125 change(1,a[1]);
126 int ans=d[a[1]];
127 for(int i=2;i<=n;i++)
128 {
129 hh=-1;
130 query_max(1,a[i],1);
131 kk=maxn;
132 query_min(a[i],n,1);
133
134 if(hh!=-1) hh=abs(d[a[i]]-d[hh]);
135 else hh=maxn;
136 if(kk!=maxn) kk=abs(d[kk]-d[a[i]]);
137 else kk=maxn;
138
139 int need=min(hh,kk);
140 ans+=need;
141 change(1,a[i]);
142 }
143 printf("%d",ans);
144 return 0;
145 }
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android自定义View实现箭头沿圆转动实例代码
- Android 中Context的使用方法详解
- Android自定义水平渐变进度条
- Android+SQLite数据库实现的生词记事本功能实例
- Android 设置颜色的方法总结
- Android支付宝支付的示例代码
- 试图解释清楚【JavaScript Event Loop】
- 结合Event Loop谈谈对Vue中nextTick的理解
- Vue3响应式原理
- ClickHouse和他的朋友们(1)编译、开发、测试
- 学会如何学习 - 成为更好的终身学习者
- ToolBar中menu无法同时显示图标和文字问题的解决方法
- Android官方的侧滑控件DrawerLayout的示例代码
- 详解React Native监听Android回退按键与程序化退出应用
- 详解android webView独立进程通讯方式