ABC 218 H 题解

ABC 218 H 题解

有一个很重要的观察\(R\)\(n-R\)的答案是一样的。

假设\(R\leq n/2\)

然后就有凸性了。

直接分治+(max,+)卷积即可。

/**
 *    author:  gary
 *    created: 11.09.2021 20:08:31
**/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define rep(a,b) for(int a=0;a<b;++a)
#define LL long long
#define PB push_back
#define POB pop_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
struct poly{
	vector<LL> v;
	poly(int n){v=vector<LL> (n,0);}
	poly(){}
	poly operator * (poly oth){//max + 卷积 
		if(oth.v.empty()) oth.v.PB(-1e15);
		if(v.empty()) v.PB(-1e15);
		int deg=oth.v.size()+v.size()-1;
		poly ret=poly(deg);
		int A=1,B=1;
		LL presum=v[0]+oth.v[0];
		ret.v[0]=presum;
		rb(i,1,ret.v.size()-1){
			LL RetA,RetB;
			if(A>=v.size()){
				RetA=-1e18;
			}
			else{
				RetA=v[A]-v[A-1];
			}
			if(B>=oth.v.size()){
				RetB=-1e18;
			} 
			else{
				RetB=oth.v[B]-oth.v[B-1];
			}
			ret.v[i]=max(RetA,RetB);
			presum+=ret.v[i];
			ret.v[i]=presum;
			if(RetA>RetB) ++A;
			else ++B;
		}
		return ret;
	}
};
void expand(poly &p,int sz){
	while(p.v.size()<sz){
		p.v.PB(-1e15);
	}
}
void chk_max(poly & A,poly B,int delta=0){
	int sz=B.v.size();
	expand(A,sz);
	rep(i,sz){
		check_max(A.v[i],B.v[i]+delta);
	}
}
const int MAXN=2e5+1;
int n,a[MAXN];
typedef tuple<poly,poly,poly,poly> T;
T solve(int l,int r){
    poly Tmp[2][2];
    if(l==r){
        T rest;
        Tmp[0][1].v=Tmp[1][0].v=vector<LL>{-1000000000000000000,-1000000000000000000};
        Tmp[0][0].v=vector<LL> {0,-1000000000000000000};
        Tmp[1][1].v=vector<LL> {-1000000000000000000,0};
        rest=make_tuple(Tmp[0][0],Tmp[0][1],Tmp[1][0],Tmp[1][1]);
        return rest;
    }
    int mid=(l+r)>>1;
    poly Lp[2][2],Rp[2][2];
    tie(Lp[0][0],Lp[0][1],Lp[1][0],Lp[1][1])=solve(l,mid);
    tie(Rp[0][0],Rp[0][1],Rp[1][0],Rp[1][1])=solve(mid+1,r);
    rep(i,2) rep(j,2) rep(k,2) rep(z,2) chk_max(Tmp[i][z],Lp[i][j]*Rp[k][z],(k!=j)*a[mid]);
    T rest;
    int len=r-l+1;
    rb(_,0,len) rep(i,2) rep(j,2) check_max(Tmp[i][j].v[_],Tmp[i^1][j^1].v[len-_]);
    rest=make_tuple(Tmp[0][0],Tmp[0][1],Tmp[1][0],Tmp[1][1]);
    return rest;
}
int main(){
    int r;
    scanf("%d%d",&n,&r);
    rb(i,1,n-1) scanf("%d",&a[i]);
    auto it=solve(1,n);
    poly answer(n+1);
    chk_max(answer,get<0>(it));
    chk_max(answer,get<1>(it));
    chk_max(answer,get<2>(it));
    chk_max(answer,get<3>(it));
    rb(i,0,n) check_max(answer.v[i],answer.v[n-i]);
    printf("%lld\n",answer.v[r]);
    return 0;
}
posted @ 2021-09-11 23:46  WWW~~~  阅读(120)  评论(0)    收藏  举报