相似於斜率優化的東西,果然CF的E之後纔會考點算法啊。ios
感受這種優化應該很常見,但這題直線只有第一象限的,可是插入,和查找操做是不變的,按極角排序後就能夠直接用這個模板了。算法
#include <iostream> #include <stdio.h> #include <string.h> #include <math.h> #include <algorithm> using namespace std; typedef long long ll; struct Line { ll a,b; ll get(ll x) { return a*x+b; } }; struct Convex_Hull { int size; Line ls[200200]; void init() { size=0; } bool is_bad(int one,int two,int three)//目前凸包集爲xxx12 要將3插入,判斷是否刪除2 { Line l1=ls[one],l2=ls[two],l3=ls[three]; return (l2.b-l1.b)*(l1.a-l3.a)>=(l3.b-l1.b)*(l1.a-l2.a);//我這樣確定能夠! } void add_line(ll a,ll b) { ls[size++] = Line{a,b};//這樣寫也能夠? while(size>=3 && is_bad(size-3, size-2, size-1) ) { ls[size-2] = ls[size-1]; size--; } } ll query(ll x) { int b=-1,d=size-1; while(d-b > 1) { int mid=(b+d)/2; if( ls[mid].get(x) <= ls[mid+1].get(x) ) { b = mid; } else d = mid; } return ls[d].get(x); } }; #define N 200200 ll sum[N]; ll ans,tans; Convex_Hull cv; int g[N]; int main() { int n; cin>>n; sum[0]=0; for(int i=1;i<=n;i++) { scanf("%d",g+i); sum[i] = sum[i-1]+g[i]; ans += (ll)i*g[i]; } cv.init(); for(int i=2;i<=n;i++) { cv.add_line(i-1, -sum[i-2]); tans = max(tans,cv.query(g[i])+sum[i-1]-(ll)i*g[i]); } //第二遍,逆着寫。 cv.init(); for(int i=n-1;i>=1;i--) { cv.add_line(-(i+1), -sum[i+1]); tans = max(tans,cv.query(-g[i])+sum[i]-(ll)i*g[i]); } cout<<ans+tans<<endl; return 0; }