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 }
作者:自为风月马前卒
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。