把那個sigma符號看成列舉。
顯然,這個函式是單峰函式,且開口向上(自己腦補一下)
然後三分。對於把所有數減去乙個數x,如何統計此時的sum值呢?
對於乙個右端點,如何找到乙個左端點使得此時的sum值最大?
對於乙個區間[x,y],我們可以由[1,y]-[1,x-1]來得到這個區間的值。
如果我們已經知道了當前的字首最小值和最大值,即對於一段區間[1,x],我們已知區間[1,i](1<=i<=x)的最小值和最大值,我們如何算出[j,x](1<=j<=x)的最小值和最大值?
我們發現,這個值只有可能是從當前字首和-字首最小值(字首最大值)得到的。
因為減去字首最小值,會讓所得到的區間盡可能的大(即求出[j,x](1<=j<=x)的最大值)。
減去字首最大值,會讓所得到的區間盡可能的小(即求出[j,x](1<=j<=x)的最小值)。
然後就能求出答案。
每次check要初始化min(字首最小值)=0,max(字首最大值)=0,ans(sum值)=0,pre(當前字首和)=0。
把搬磚的過程建成一棵樹,根節點有所有的磚頭,然後每次分成最多三個兒子。每個葉子節點可以看成每個工地。
我們可以發現,最終的答案就是每個點的點權(工地的所需磚頭數)乘以深度的最小值。(根節點的深度為0)
我們想到了什麼?三叉huffman樹!
由於我們要讓它的深度盡量小,所以我們每個節點要盡量分3叉或者不分。
但是萬一題目給出的數是偶數呢?補乙個點權為0的節點,照常構造三叉huffman樹。(其實這棵樹不用真正的建出來,我們只需要計算答案就行了)
還有一種思考方式:考慮到分磚頭太難,我們考慮合併磚頭。則題意變為:有n堆磚頭,我們要把這些磚頭合併成一堆。每次最多合併3堆磚頭。合併的代價為你合併的磚頭總數。求最小代價。
合併果子!這就比較好做,貪心,每次合併最小3堆。可是,偶數怎麼辦呢?
偶數就意味著你最後合併完了後只剩兩堆,但這樣合併一般不優啊。所以,我們就考慮先合併最小的兩堆,然後3堆3堆的合。
至於為什麼要合併最小的兩堆,我們可以看成,這裡還有一堆0個磚頭,這樣我們就要把這三堆合併。即先合併最小的兩堆。
#include#includeview code#include
using
namespace
std;
long
long ans=0
;priority_queue
long,vector
long>,greater
long> >q;
intmain()
if(n==1)
if(n%2==0)
while(q.size()>1
)
printf(
"%lld
",ans);
return0;
}
20161104校內訓練
一道類似模擬的題,就根據所寫的東西來做就可以了。include define rep i l r for int i l i r i define per i r l for int i r i l i define erep i u for int i head u i i e i nxt usi...
2017 4 14校內訓練
hzwer拿了幾道noi中比較簡單的給我們做 a.noi2009 植物大戰殭屍 思路 考慮最小割,如果乙個植物的權值x是正的,我們先預設吃掉它,使答案加上x並讓s向這個點連x,割這條邊相當於不吃這個植物,否則讓這個點向t連 x,割這條邊相當於吃這個植物,每個植物讓它能攻擊到的格仔和它的前一格向它連i...
2017 4 7校內訓練
喪病hzwer的ctsc訓練賽 my ac 3 4 a.ctsc2014 企鵝qq 思路 亂hash,我比較菜,寫的醜 各種wa tle,好久才a掉。include include using namespace std define ll long long define mn 200 defin...