https://www.luogu.org/problem/show?pid=2234
题目描述
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
ct,该记l,r还是要记得。。
以权值为下标建一颗线段树.
每次插一个新值, 并查询大于它的最小值和小于它的最大值.
1 #include <algorithm> 2 #include <cstdio> 3 4 using namespace std; 5 6 const int N(32767+666); 7 int n,a[N],mark[N]; 8 9 struct Node 10 { 11 int a,mark; 12 }node[N]; 13 bool cmp(Node c,Node b) 14 { 15 return c.a<b.a; 16 } 17 18 #define lc (now<<1) 19 #define rc (now<<1|1) 20 #define INF 0x7fffffff 21 struct Tree 22 { 23 int l,r,maxx,minn,val; 24 }tree[N<<2]; 25 void Pushup(int now) 26 { 27 tree[now].val=tree[lc].val+tree[rc].val; 28 tree[now].maxx=max(tree[lc].maxx,tree[rc].maxx); 29 tree[now].minn=min(tree[lc].minn,tree[rc].minn); 30 } 31 void Build(int now,int l,int r) 32 { 33 tree[now].l=l; 34 tree[now].r=r; 35 tree[now].maxx=-1; 36 tree[now].minn=INF-1; 37 if(l==r) return ; 38 int mid=l+r>>1; 39 Build(lc,l,mid); 40 Build(rc,mid+1,r); 41 } 42 void Change(int now,int x) 43 { 44 if(tree[now].l==tree[now].r) 45 { 46 tree[now].val=1; 47 tree[now].maxx=tree[now].l; 48 tree[now].minn=tree[now].r; 49 return ; 50 } 51 int mid=tree[now].l+tree[now].r>>1; 52 if(x<=mid) Change(lc,x); 53 if(x>mid) Change(rc,x); 54 Pushup(now); 55 } 56 int Q_max(int now,int L,int R) 57 { 58 if(R<L) return -1; 59 if(tree[now].val==0) return -1; 60 if(tree[now].l>=L&&tree[now].r<=R) return tree[now].maxx; 61 int tmp=-2; 62 int mid=tree[now].l+tree[now].r>>1; 63 if(L<=mid) tmp=max(tmp,Q_max(lc,L,R)); 64 if(R>mid) tmp=max(tmp,Q_max(rc,L,R)); 65 return tmp; 66 } 67 int Q_min(int now,int L,int R) 68 { 69 if(R<L) return INF-1; 70 if(tree[now].val==0) return INF-1; 71 if(tree[now].l>=L&&tree[now].r<=R) return tree[now].minn; 72 int tmp=INF,mid=tree[now].l+tree[now].r>>1; 73 if(L<=mid) tmp=min(tmp,Q_min(lc,L,R)); 74 if(R>mid) tmp=min(tmp,Q_min(rc,L,R)); 75 return tmp; 76 } 77 78 int main() 79 { 80 scanf("%d",&n); 81 for(int i=1;i<=n;i++) 82 { 83 scanf("%d",&node[i].a); 84 node[i].mark=i; 85 } 86 sort(node+1,node+n+1,cmp); 87 int cnt=1; 88 a[1]=node[1].a; 89 mark[node[1].mark]=cnt; 90 for(int i=2;i<=n;i++) 91 { 92 if(node[i-1].a!=node[i].a) cnt++; 93 a[cnt]=node[i].a; 94 mark[node[i].mark]=cnt; 95 } 96 Build(1,1,cnt); 97 int ans=a[mark[1]]; 98 Change(1,mark[1]); 99 for(int i=2;i<=n;i++) 100 { 101 int tmp=INF,maxx=Q_max(1,1,mark[i]),minn=Q_min(1,mark[i]+1,n); 102 if(maxx!=-1) tmp=min(tmp,a[mark[i]]-a[maxx]); 103 if(minn!=INF-1) tmp=min(tmp,a[minn]-a[mark[i]]); 104 ans+=tmp; 105 Change(1,mark[i]); 106 } 107 printf("%d",ans); 108 return 0; 109 }