1. 程式人生 > >BZOJ 1588: [HNOI2002]營業額統計

BZOJ 1588: [HNOI2002]營業額統計

LG mes www. stat 這一 要求 names 復雜 維護

1588: [HNOI2002]營業額統計

Time Limit: 5 Sec Memory Limit: 162 MB
Submit: 18803 Solved: 7912
[Submit][Status][Discuss]

Description

營業額統計 Tiger最近被公司升任為營業部經理,他上任後接受公司交給的第一項任務便是統計並分析公司成立以來的營業情況。 Tiger拿出了公司的賬本,賬本上記錄了公司成立以來每天的營業額。分析營業情況是一項相當復雜的工作。由於節假日,大減價或者是其他情況的時候,營業額會出現一定的波動,當然一定的波動是能夠接受的,但是在某些時候營業額突變得很高或是很低,這就證明公司此時的經營狀況出現了問題。經濟管理學上定義了一種最小波動值來衡量這種情況: 該天的最小波動值 當最小波動值越大時,就說明營業情況越不穩定。 而分析整個公司的從成立到現在營業情況是否穩定,只需要把每一天的最小波動值加起來就可以了。你的任務就是編寫一個程序幫助Tiger來計算這一個值。 第一天的最小波動值為第一天的營業額。 ? 輸入輸出要求

Input

第一行為正整數 ,表示該公司從成立一直到現在的天數,接下來的n行每行有一個整數(有可能有負數) ,表示第i 天公司的營業額。 天數n<=32767, 每天的營業額ai <= 1,000,000。 最後結果T<=2^31

Output

輸出文件僅有一個正整數,即Sigma(每天最小的波動值) 。結果小於2^31 。

Sample Input

6
5
1
2
5
4
6

Sample Output

12

思路:

  顯然,對於每天考慮前面的數對該數的前驅和後繼,做差選一個絕對值最小的累加答案。所以只需要考慮如何查找前驅後繼即可,維護一顆平衡樹 (Treap,Splay什麽的)。

手指在打籃球的時候傷了, 我就上一個紅黑樹吧

代碼如下

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
int n;
int ans,now;
set <int> s;
set <int>::iterator s1;
using namespace std;
int main() {
	scanf("%d",&n);
	n--;
	int p;
	scanf("%d",&p);
	s.insert(p);
	ans=p;
	while(n--) {
		scanf("%d",&p);
		s1 = s.lower_bound(p);
		int t = 0x3f3f3f3f;
		if(s1 != s.end()) {
			t=min(t,abs((*s1) - p));
		}
		if(s1 != s.begin()) {
			t=min(t,abs((*--s1)-p));
		}
		ans+=t;
		s.insert(p);
	}
	printf("%d",ans);
}

>原文鏈接<

學set先看這裏>FCWww<

BZOJ 1588: [HNOI2002]營業額統計