BZOJ 1911 [APIO2010]特別行動隊


題目描述
這裏寫圖片描述


因爲是從別人博客裏斜率優化分類一欄找的題目,所以…這題被我秒了。

顯然先預處理前綴和s(i)=ik=1xi
d(i) 爲將前i 個士兵分組的最大修正後戰鬥力。

d(i)===max{ d(j)+a(s(i)s(j))2+b(s(i)s(j))+c }max{ d(j)+a×s(i)22a×s(i)s(j)+a×s(j)2+b×s(i)b×s(j)+c }max{ d(j)2a×s(i)s(j)+a×s(j)2b×s(j) }+a×s(i)2+b×s(i)+c


KiXjBiYj====2a×s(i)s(j)d(i)a×s(i)2b×s(i)cd(j)+a×s(j)2b×s(j)

直線解析式爲KiXj+Bi=Yj 其中斜率Ki 單減,Xj 單增。
代碼
#include<cstdio>
#include<iostream>
#include<cstring>
#define k(A) (2*a*s[A])
#define x(A) s[A]
#define b(A) (d[A]-a*s[A]*s[A]-b*s[A]-c)
#define y(A) (d[A]+a*s[A]*s[A]-b*s[A])
using namespace std;
const int maxn=1000010;
long long d[maxn],s[maxn];
int q[maxn],n,a,b,c;
double slope(int i,int j){
    return 1.0*(y(i)-y(j))/(x(i)-x(j));
}
int main(){
    cin>>n>>a>>b>>c;
    s[0]=q[0]=d[0]=0;
    for(int i=1;i<=n;i++){
        int x;
        scanf("%d",&x);
        s[i]=s[i-1]+x;
    }
    int head=0,tail=0;
    for(int i=1;i<=n;i++){
        while(head<tail&&slope(q[head],q[head+1])>k(i)) head++;
        d[i]=-(k(i)*x(q[head])-y(q[head])-a*s[i]*s[i]-b*s[i]-c);
        while(head<tail&&slope(q[tail-1],q[tail])<=slope(q[tail],i)) tail--;
        q[++tail]=i;
    }
    cout<<d[n]<<endl;
}
發佈了59 篇原創文章 · 獲贊 4 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章