原題連結:https://www.luogu.com.cn/problem/P2234
題意解讀:要計算每一天最小波動值的和,需要對每一天求最小波動值,再求和,如果暴力法,時間複雜度在1+2+3+......+32767≈5*10^8,可能會超時。
解題思路:
1、暴力法:由於本題測試資料比較水,實測暴力求解直接可以AC,由於沒有技術含量,不做具體介紹。
2、set法:
對於每一個數x,只需要找前面出現的跟x最接近的數
那麼,很容易想到,對出現的每一個數,維護一個有序的資料結構,當把x插入之前,找到x的前後數(剛好>=x的、剛好<x的),看差的絕對值哪個小即可
要維護有序的資料結構,set比較合適,另外set還提供了lower_bound(x)函式,可以在logN的複雜度查詢第一個>=指定值的位置
100分程式碼:
#include <bits/stdc++.h>
using namespace std;
set<int> st;
int ans;
int main()
{
int n, x;
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> x;
int minx = INT_MAX;
if(i == 1) minx = x;
else
{
set<int>::iterator itr = st.lower_bound(x); //先查詢>=x的第一個數的位置
if(itr != st.end()) minx = min(minx, abs(*itr - x)); //計算第一個可能的最小波動值
if(itr != st.begin())
{
set<int>::iterator itl = itr;
itl--; //itl是<x的最大的數的位置
minx = min(minx, abs(*itl - x)); //計算第二個可能的最小波動值
}
}
st.insert(x); //將x插入set
ans += minx;
}
cout << ans;
return 0;
}