點此看題
感覺這道題網上講解不是特別清楚,我來補一發詳細講解吧,因為作者也是花了好久才搞懂。
首先把題目所求轉化成形式化表達(其中s
ss是生命值a
aa的字首和):
∑ i=
1nmaxj=
1is[
i]−s
[j−1
]x[i
]+(i
−j)d
\sum_^n\max_^i \frac
i=1∑n
j=1maxi
x[i]
+(i−
j)ds
[i]−
s[j−
1]是不是感覺難以優化,我們改換一種寫法:
∑ i=
1nmaxj=
1is[
i]−s
[j−1
]x[i
]+id
−jd\sum_^n\max_^i \frac
i=1∑n
j=1maxi
x[i]
+id−
jds[
i]−s
[j−1
]有點眼熟,可以轉化為兩個點(x[
i]+i
d,s[
i]),
(jd,
s[j−
1])(x[i]+id,s[i]),(jd,s[j-1])
(x[i]+
id,s
[i])
,(jd
,s[j
−1])
直線的斜率,對於後者,我們維護乙個凸包,為什麼要維護凸包呢?因為原問題在二維平面上是乙個頂點到若干個點的最大斜率問題,看下圖!
可見在定點到凸包上點的斜率與凸包相切的時候斜率是最大的,當這樣的點往前取和往後取答案都會減少,這種單調性給了我們快速解決問題的可能。補充乙個問題:為什麼凸包要維護單調遞增的呢?我們還是結合圖來分析,比如下面就是乙個斜率單調遞減的圖,你仔細看看就知道中間的點永遠不可能是答案。
接著單調性往下講,我們可以考慮用二分來算答案,由於最優解是在中間的,我們二分出mid
midmi
d,比較它和mid
−1mid-1
mid−
1跟定點連成的斜率誰是更大的,如果mid
midmi
d更大,那麼往右邊分,記錄答案,否則往左邊分。那麼時間複雜度就做到了o(n
logn)
o(n\log n)
o(nlogn)
,還有不懂請看**。
#include
const
int m =
100005
;#define int long long
#define db double
intread()
while
(c>=
'0'&& c<=
'9')
return x*f;
}int n,d,top,s[m]
,a[m]
,b[m]
;db ans;
db slope
(int x,
int y)
signed
main()
s[0]=
1;//防re
for(
int i=
1;i<=n;i++
) ans+
=1.0
*(a[i]
-a[s[t]-1
])/(b[i]
+(i-s[t]
)*d);}
printf
("%.0f\n"
,ans)
;}
SDOI2013 保護出題人
出題人銘銘認為給sdoi2012 出題太可怕了,因為總要被罵,於是他又給sdoi2013 出題了。參加sdoi2012 的小朋友們釋放出大量的殭屍,企圖攻擊銘銘的家。而你作為sdoi2013的參賽者,你需要保護出題人銘銘。殭屍從唯一一條筆直道路接近,你們需要在銘銘的房門前放置植物攻擊殭屍,避免殭屍碰...
Sdoi2013 保護出題人 三分 單調棧
description 題意好長啊,自己去看吧。sample input 5 2 3 3 1 1 10 8 4 8 2 3sample output 7設a的字首和為s 這道題首先可以推出乙個式子,第i位答案為 max s i s j 1 d i d i j 然後能拿60分。然後維護乙個下凸包,然後...
SDOI2013 BZOJ3203 保護出題人
description input 第一行兩個空格隔開的正整數n和d,分別表示關數和相鄰殭屍間的距離。接下來n行每行兩個空格隔開的正整數,第i 1行為ai和 xi,分別表示相比上一關在殭屍佇列排頭增加血量為ai 點的殭屍,排頭殭屍從距離房子xi公尺處開始接近。output 乙個數,n關植物攻擊力的最...