在乙個序列 \(\\) 裡找到乙個非空子段 \(\\), 滿足 \(\sum\limits_^b_i\times i\) 最大
\(n\le 200000,|a_i|\le 2000\)
長的都一臉的斜率優化
考慮表示乙個子段\([l+1,r]\)為
\[\begin
&\sum_^ra_i(i-l)\\
&=\sum_^ra_i\times i-a_i\times l
\end
\]設\(a_k=\sum_^k a_ii,b_k=\sum_^k a_i\)
那繼續化簡為
\[a_r-b_r\times l+b_l\times l-a_l
\]然後我們列舉\(r\),想辦法搞一下\(l\)
維護乙個\((i,b_i\times i-a_i)\)的上凸包,然後發現是對斜率詢問最大截距,直接在凸包上三分就可以了。
code:
#include #include #define ll long long
const int n=2e5+10;
using std::max;
int n,tot;
ll a[n],b[n];
struct point
point(ll x,ll y)
point friend operator -(point a,point b)
ll cal(ll d)
}s[n];
ll cross(point a,point b)
void ins(point a)
int main()
{ scanf("%d",&n);
ins(point(0,0));
ll ans=-(1ll<<50),a;
for(int i=1;i<=n;i++)
{ scanf("%lld",&a);
a[i]=a[i-1]+a*i;
b[i]=b[i-1]+a;
int l=1,r=tot;
while(l>1;
if(s[mid].cal(-b[i])2019.2.16
Newcoder練習賽40D 小A與最大子段和
題目 挺好的一道題 我們考慮把 i 作為選取的最大子段的結束位置,我們如何往前計算貢獻呢 考慮一下這個乘上其在佇列中的位置可以表示為這個數被算了多少次,而我們往前擴充套件一位當前已經被擴充套件的就會被計算一次 設 s i 表示序列的字首和 擴充套件一次 s i s 再擴充套件一次 s i s s i...
牛客練習賽41 最小相似度 解題報告
思路不錯的題目 考慮到總體的狀態數只有 2 m 中,如果我們把某個串改變1位,這個改變後的串和這個串的答案就是 m 1 由此可見,每個串到另乙個串都有乙個距離,我們把這個距離設為改變的位數,所有串到某個串都有乙個最小位數 x 這個最小位數的最大值 y 的答案 m y 就是我們的答案。我們發現這就是乙...
牛客練習賽 小trick 托公尺搭積木
這天,可愛的小托公尺得到了n堆積木,且第i堆積木初始時有ai塊積木.小托公尺很快就喜歡上了玩積木.他會作出三種操作 1.把第v堆的積木數量更改為x.2.在每堆積木的上面都加上y個積木.3.數第q堆積木的積木個數.由於這天可愛的小托公尺實在是太睏了,所以他請你幫他完成這些操作.輸入描述 第一行兩個整數...