對於乙個給定的序列a1, …, an,我們對它進行乙個操作reduce(i),該操作將數列中的元素ai和ai+1用乙個元素max(ai,ai+1)替代,這樣得到乙個比原來序列短的新序列。這一操作的代價是max(ai,ai+1)。進行n-1次該操作後,可以得到乙個長度為1的序列。
我們的任務是計算代價最小的reduce操作步驟,將給定的序列變成長度為1的序列。
第一行為乙個整數n( 1 <= n <= 1,000,000 ),表示給定序列的長度。
接下來的n行,每行乙個整數ai(0 <=ai<= 1, 000, 000, 000),為序列中的元素。
只有一行,為乙個整數,即將序列變成乙個元素的最小代價。
輸入 #1
312
3
輸出 #1
5
提示
30%的測試資料 n<=500;
50%的測試資料 n <= 20,000。
經過本蒟蒻的深思熟慮之後,認為此題分為四種情況.
1.單調序列
對於序列中的元素合併整個序列的最小代價為
∑ i=
2len
ai∑i
=1le
n−1a
i\sum_^a_i\sum_^a_i
i=2∑le
nai
i=1
∑len
−1a
i2.有乙個波峰的序列
從波峰兩側向波峰合併是最優方案。設波峰是t號元素,則最小代價為
∑ i=
2tai
+∑i=
tlen
−1ai
=at+
∑2le
n−1a
i\sum_^a_i + \sum_^a_i = a_t + \sum_^a_i
i=2∑t
ai+
i=t∑
len−
1ai
=at
+2∑
len−
1ai
3.有兩個波峰的序列
維護乙個單調棧,將出棧序列合併後與入棧元素合併,同時計算代價。
4.任意序列
其實就是將兩個波峰的情況擴充套件到多個波峰,同情況3。
#includeusing namespace std;
const int maxn=1e6+100;
int s[maxn],a[maxn];
int main()
s[++p]=(long long)a[i];}}
for(int i=1;iprintf("%lld\n",ans);
return 0;
}
P4392 BOI2007 Sound 靜音問題
數字錄音中,聲音是用表示空氣壓力的數字序列描述的,序列中的每個值稱為乙個取樣,每個取樣之間間隔一定的時間。很多聲音處理任務都需要將錄到的聲音分成由靜音隔開的幾段非靜音段。為了避免分成過多或者過少的非靜音段,靜音通常是這樣定義的 m個取樣的序列,該序列中取樣的最大值和最小值之差不超過乙個特定的閾值c。...
P4392 BOI2007 Sound 靜音問題
本題其實可以拆解程兩個問題,求區間最大值 求區間最小值。而這兩個操作都必須在 o log n 內完成。自然想到線段樹。線段樹需要維護兩個資訊 區間最大值 區間最小值。輸入完資料後,建樹。然後遍歷序列,求區間最大值最小值之差,再判斷是否大於 c 就可以了。記得立乙個 flag 方便記錄是否有解。很重要...
BOI2007 名次排序問題 sorting
已知參賽選手的得分,你的任務是按照得分從高到底給出選手的排名。遺憾的是,儲存選手資訊的資料結構只支援一種操作,即將乙個選手從位置i移動到位置j,該移動不改變其他選手的相對位置,即如果i j,位置j和位置i 1之間的選手的位置都比原來加1,相反如果 i j,則位置i 1和位置j之間的選手的位置都比原來...