https://www.luogu.com.cn/problem/CF660F
找区间的题想到分治。
假如考虑怎么计算跨 mid 的贡献。
假如 i∈[l,mid] 的答案为 ansi(右端点为 mid),右边的答案为 j∈[mid+1,r],ansj (左端点为 mid+1),那么答案显然是 ansi+(mid−i+1)∗sumj+ansj,实际上就是把右边的看成一个个一次函数,求在 mid−i+1 的最大值。
李超线段树即可。
#include <bits/stdc++.h>
#define int long long
#define pb push_back
using namespace std;
const int N=(int)(2e5+5);
int n,a[N];
#define ls (cur<<1)
#define rs (ls|1)
struct node {
int k,b;
}s[N];
int val[N<<2];
int cal(int id,int x) {
return s[id].k*x+s[id].b;
}
int clr[N<<4],clrtot;
void update(int cur,int l,int r,int cl,int cr,int id) {
int mid=(l+r)>>1,v=val[cur];
if(cl<=l&&r<=cr) {
clr[++clrtot]=cur;
int res1=cal(v,mid),res2=cal(id,mid);
if(l==r) {
if(!val[cur]) val[cur]=id;
else {
if(res2>res1) val[cur]=id;
}
return ;
}
if(s[id].k>s[v].k) {
if(res2>res1) val[cur]=id,update(ls,l,mid,cl,cr,v);
else update(rs,mid+1,r,cl,cr,id);
} else if(s[id].k<s[v].k) {
if(res2>res1) val[cur]=id,update(rs,mid+1,r,cl,cr,v);
else update(ls,l,mid,cl,cr,id);
} else if(s[id].b>s[v].b) val[cur]=id;
return ;
}
if(cl<=mid) update(ls,l,mid,cl,cr,id);
if(cr>mid) update(rs,mid+1,r,cl,cr,id);
}
int query(int cur,int l,int r,int pos) {
if(r<pos||l>pos) return 0;
int mid=(l+r)>>1,res=cal(val[cur],pos);
if(l==r) return res;
if(pos<=mid) res=max(res,query(ls,l,mid,pos));
else res=max(res,query(rs,mid+1,r,pos));
return res;
}
void RE(int cur,int l,int r) {
val[cur]=0;
if(l==r) return ;
int mid=(l+r)>>1;
RE(ls,l,mid); RE(rs,mid+1,r);
}
int ans=0,tmp[N],sm[N];
void solve(int l,int r) {
if(l==r) {
ans=max(ans,a[l]); return ;
}
int mid=(l+r)>>1;
solve(l,mid); solve(mid+1,r);
tmp[mid]=sm[mid]=0; int cnt=0;
for(int i=mid+1;i<=r;i++) {
tmp[i]=tmp[i-1]+(i-mid)*a[i];
sm[i]=sm[i-1]+a[i];
s[++cnt].k=sm[i]; s[cnt].b=tmp[i];
}
clrtot=0;
for(int i=1;i<=cnt;i++) update(1,1,n,1,n,i);
int res=0;
for(int i=l;i<=mid;i++) res+=+a[i]*(i-l+1);
int qwq=0;
for(int i=l;i<=mid;i++) qwq+=a[i];
for(int i=l;i<=mid;i++) {
ans=max(ans,res+query(1,1,n,mid-i+1));
res-=qwq; qwq-=a[i];
}
for(int i=1;i<=clrtot;i++) val[clr[i]]=0;
for(int i=l;i<=r;i++) tmp[i]=sm[i]=0;
}
signed main() {
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
solve(1,n); cout<<ans;
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】