【題解】CF631E Product Sum

CF631E Product Sum

\(\text{Solution:}\)

考慮轉化操作,顯然有,設從 \(i\) 轉移到 \(j,\)\(i>j\) 貢獻則爲 \(s_{i-1}-s_{j}-(i-j)\times a_i,s_i=\sum_{i=1}^n a_i\)

如果 \(i<j\) 則貢獻爲 \((j-i)\times a_i-(s_j-s_i)\)

這東西拆出來發現就是斜率優化。直接李超樹維護即可 \(O(n\log n),\) 注意要正反來兩遍

順便學習一下很短的李超樹寫法,每次令當前點是中點處值小的直線,則斜率小就往左邊走,否則往右邊走。代碼就很短了。

注意需要特判邊界,代碼裏面是動態開點,走到不存在的點應當返回 $-\infty $

簡潔版本代碼:

#include <bits/stdc++.h>
using namespace std;
typedef double db;
#define int long long
#define fi first
#define se second
#define mk make_pair
#define pb emplace_back
#define poly vector<int>
#define Bt(a) bitset<a>
#define bc __builtin_popcount
#define pc putchar
#define ci const int&
const int mod = 1e9 + 7;
const db eps = 1e-10;
const int inf = (1LL << 60);
inline int Max(ci x, ci y) {return x > y ? x : y;}
inline int Min(ci x, ci y) {return x < y ? x : y;}
inline db Max(db x, db y) {return x - y > eps ? x : y;}
inline db Min(db x, db y) {return x - y < eps ? x : y;}
inline int Add(ci x, ci y, ci M = mod) {return (x + y) % M;}
inline int Mul(ci x, ci y, ci M = mod) {return 1ll * x * y % M;}
inline int Dec(ci x, ci y, ci M = mod) {return (x - y + M) % M;}
typedef pair<int, int> pii;
inline int Abs(int x) {return x < 0 ? -x : x;}
char buf[1<<21],*p1=buf,*p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char Obuf[105000],*O=Obuf;//Siz shoule be the size of Out File
int pst[30],ptop;
inline void Fprint(){fwrite(Obuf,1,O-Obuf,stdout);}
inline void Fwrite(int x){
  if(x==0){*O++='0';return;}
  if(x<0)*O++='-',x=-x;ptop=0;
  while(x)pst[++ptop]=x%10,x/=10;
  while(ptop)*O++=pst[ptop--]+'0';
  if(O-Obuf>100000)Fprint(),O=Obuf;
}
inline int read() {
    int s = 0, w = 1;
    char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') w = -1;ch = getchar();}
    while (isdigit(ch)) {s = s * 10 + ch - '0';ch = getchar();}
    return s * w;
}
inline void write(int x) {
    if (x < 0)putchar('-'), x = -x;
    if (x > 9)write(x / 10);
	pc(x % 10 + '0');
}
inline int qpow(int x, int y) {
    int res = 1;
    while (y) {if (y & 1)res = Mul(res, x);x = Mul(x, x);y >>= 1;}
    return res;
}
inline void cadd(int &x, int y) {x += y;}
inline void cmul(int &x, int y) {x *= y;}
inline void cmax(int &x, int y) {x = Max(x, y);}
inline void cmin(int &x, int y) {x = Min(x, y);}
const int N = 2e5 + 10;
namespace Refined_heart{
	int n,sum[N],a[N];
	namespace LiChao{
		const int M=7e6+10;
		struct Node{
			int k,b;
			inline int calc(int x){return k*x+b;}
		}tr[M];
		int node,rt,ls[M],rs[M];
		inline int CL(int k,int b,int x){return k*x+b;}
		void insert(int &x,int l,int r,int k,int b){
			if(!x)x=++node;
			int mid=(l+r)>>1;
			int now=tr[x].calc(mid);
			int cg=CL(k,b,mid);
			if(!tr[x].k){
				tr[x].k=k;tr[x].b=b;
				return;
			}
			if(cg>now){
				int kk=tr[x].k,bb=tr[x].b;
				tr[x].k=k;tr[x].b=b;b=bb;k=kk;
			}
			if(l!=r){
				if(k<tr[x].k)insert(ls[x],l,mid,k,b);
				else insert(rs[x],mid+1,r,k,b);
			}
		}
		int query(int x,int l,int r,int v){
			if(!x)return -inf;
			int ans=tr[x].calc(v);
			if(l==r)return ans;
			int mid=(l+r)>>1;
			ans=Max(ans,v<=mid?query(ls[x],l,mid,v):query(rs[x],mid+1,r,v));
			return ans;
		}
	}
	using namespace LiChao;
	int f[N],g[N];
	void solve(){
		n=read();
		for(int i=1;i<=n;++i)a[i]=read();
		for(int i=1;i<=n;++i)sum[i]=sum[i-1]+a[i];
		int ans=0;
		for(int i=1;i<=n;++i)ans+=i*a[i];
		int v=-inf;
		for(int i=1;i<=n;++i){
			
			f[i]=query(rt,-1000001,1000001,a[i])+sum[i-1]-i*a[i];
			insert(rt,-1000001,1000001,i,-sum[i-1]);
		}
		for(int i=0;i<=n;++i)cmax(v,ans+f[i]);
		for(int i=0;i<=node;++i)tr[i]=(Node){0,0},ls[i]=0,rs[i]=0;
		node=0;rt=0;
		for(int i=n;i>=1;--i){
			
			g[i]=query(rt,-1000001,1000001,a[i])+sum[i]-i*a[i];
			insert(rt,-1000001,1000001,i,-sum[i]);
		}
		for(int i=0;i<=n;++i)cmax(v,ans+g[i]);
		write(v);pc('\n');
	}
}
signed main(){
	freopen("in.txt","r",stdin);
	Refined_heart::solve();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章