[BZOJ3675][Apio2014]序列分割

来源:互联网 发布:二维数组去重js 编辑:程序博客网 时间:2024/06/06 20:18

原题地址

分割的顺序影响答案的话不好搞,于是推推式子发现k=2时分割的顺序不影响答案,再YY一下可以证出k>2时分割的顺序也不影响答案.
然后我们考虑从左到右分割,DP+斜率优化不难写出(f[],g[]那里要多想想).

#include <cstdio>#include <queue>using namespace std;typedef long long ll;const ll N=100010;const ll INF=1<<30;ll n,k,ans;ll a[N],s[N],f[N],g[N];struct Vec{    ll x,y;    Vec() {}    Vec(ll x,ll y):x(x),y(y) {}    friend Vec operator-(Vec a,Vec b){        return Vec(a.x-b.x,a.y-b.y);    }    friend ll operator*(Vec a,Vec b){        return a.x*b.y-a.y*b.x;    }};int main(){    scanf("%lld%lld",&n,&k);    for(ll i=1;i<=n;i++) scanf("%lld",&a[i]);    for(ll i=1;i<=n;i++) s[i]=s[i-1]+a[i];    f[0]=-(INF*INF);    for(ll i=1;i<=n;i++) f[i]=s[i]*(s[n]-s[i]);    for(ll i=2;i<=k;i++){        deque<Vec> Q;        for(ll j=0;j<=n;j++) g[j]=f[j];        for(ll j=1;j<=n;j++){            ll  A=s[j];            Vec tmp=Vec(s[j-1],g[j-1]-s[n]*s[j-1]);            while(Q.size()>1){                Vec a,b;                a=Q.front();Q.pop_front();b=Q.front();                if((tmp-a)*(a-b)>0){                    Q.push_front(a);                    break;                }            }            Q.push_front(tmp);            while(Q.size()>1){                Vec a,b;                a=Q.back();Q.pop_back();b=Q.back();                if(A*a.x+a.y>A*b.x+b.y){                    Q.push_back(a);                    break;                }            }            tmp=Q.back();            f[j]=A*tmp.x+tmp.y+s[n]*s[j]-s[j]*s[j];        }    }    for(ll i=1;i<=n;i++) ans=f[i]>ans?f[i]:ans;    printf("%lld\n",ans);    return 0;}
0 0
原创粉丝点击