CF660F Bear and Bowling 4

https://www.luogu.com.cn/problem/CF660F

找区间的题想到分治。

假如考虑怎么计算跨 mid 的贡献。

假如 i[l,mid] 的答案为 ansi(右端点为 mid),右边的答案为 j[mid+1,r],ansj (左端点为 mid+1),那么答案显然是 ansi+(midi+1)sumj+ansj,实际上就是把右边的看成一个个一次函数,求在 midi+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]; // cout<<cur<<" "<<l<<" "<<r<<" "<<cl<<" "<<cr<<" "<<id<<'\n'; 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; // cout<<l<<' '<<r<<'\n'; 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++) { // int nw=0; // for(int j=l;j<=mid;j++) nw+=(j-l+1)*a[j]; 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.tie(0); ios::sync_with_stdio(false); cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; solve(1,n); cout<<ans; return 0; }

__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/16477339.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示