YbtOJ#493-最大分数【斜率优化dp,分治】

1|0正题

题目链接:http://www.ybtoj.com.cn/contest/117/problem/1


1|1题目大意

n个数的一个序列,给其中的一些数打上标记。
一个标记方案的贡献为s1表示有多少对L,R满足区间[L,R]都被打上了标记,s2表示标记的数字和。贡献为s1s2

m次询问,修改一个数后,求最大的可能贡献(询问之间相互独立)

1n,m3×105


1|2解题思路

先把答案减去一个i=1nai,这样就变为对于一段[L,R]要么选择s1要么选择s2
先考虑不带修改怎么搞,设fi表示前i个的最大贡献。

定义si=j=1iai然后有方程

fi=max{fj+max{sisj,(ij2)}}

这个东西可以斜率优化搞(考场上犯病写了个CDQ,调了我半天)

然后带修改,考虑到每次只会影响一个数字,可以理解为一个前缀和后缀拼起来。把刚刚那个dp再反过来做一次记为gi

那么现在对于修改的位置x,我们要么选择x,要么跨过x,也就是最大化

max{fj+gi+si1sj,fj+gi+(ij12)}(i[0,x1],j[x+1,n+1])

前面那个可以把两个前/后缀的max的fjsjgi+si1加起来就好了。

后面那个考虑分治,我们每次分治到一个位置[l,mid,r],如果需要往左走就统计i[0,l1]j[mid+1,r]的答案。右边同理。

因为我们的每次的时间复杂度是外面的大小,所以我们可以维护一个前后缀的凸壳,然后在上面二分时间复杂度就是O(nlog2n)的。

同时维护两个凸壳需要回溯所以很麻烦,分开两次正反做一次就好了。

时间复杂度O(nlog2n)


1|3code

(考场代码,有点丑)

#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define ll long long using namespace std; const ll N=3e5+10,inf=1e18; ll n,m,ans,lmax,rmax,top,st[N],suf[N]; ll a[N],f[N],g[N],s[N],prt[N],w[N],yf[N]; vector<ll > q[N]; ll px(ll x,ll *f) {return f[x]*2+x*x-x;} ll xj(ll x1,ll y1,ll x2,ll y2) {return x1*y2-x2*y1;} ll xl(ll a,ll b,ll c,ll *f){ ll y1=px(b,f)-px(a,f),x1=b-a; ll y2=px(c,f)-px(a,f),x2=c-a; return xj(x1,y1,x2,y2); } ll ck(ll l,ll r,ll *f) {return f[l]+(r-l+1)*(r-l)/2;} ll solve(ll l,ll r,ll *f){ if(l==r)return f[l]-s[l]; ll mid=(l+r)>>1; ll maxs=solve(l,mid,f);top=0; for(ll i=l;i<=mid;i++){ while(top>1&&xl(st[top-1],st[top],i,f)>=0)top--; st[++top]=i; } for(ll i=mid+1;i<=r;i++){ while(top>1&&ck(st[top],i,f)<ck(st[top-1],i,f))top--; f[i]=max(f[i],max(ck(st[top],i,f),s[i]+maxs)); } maxs=max(maxs,solve(mid+1,r,f)); return maxs; } ll cw(ll l,ll r) {return f[l]+g[r]+(r-l-1)*(r-l)/2;} ll xll(ll a,ll b,ll c){ ll y1=(yf[b]-yf[a])*2,x1=b-a; ll y2=(yf[c]-yf[a])*2,x2=c-a; return xj(x1,y1,x2,y2); } ll xlr(ll a,ll b,ll c){ ll y1=yf[b]-yf[a],x1=(n-b+1)-(n-a+1); ll y2=yf[c]-yf[a],x2=(n-c+1)-(n-a+1); return xj(x1,y1,x2,y2); } void calc(ll L,ll R){ if(L==R){ for(ll i=0;i<q[L].size();i++){ ll x=q[L][i],tmp; prt[x]=max(ans-w[x]+a[L]-s[n],prt[x]); } while(top>1&&xll(st[top-1],st[top],L)>=0)top--; st[++top]=L; return; } ll mid=(L+R)>>1,pa=ans; if(top){ for(ll i=mid+1;i<=R;i++){ ll l=1,r=top-1; while(l<=r){ ll x=(l+r)>>1; if(cw(st[x],i)<=cw(st[x+1],i))l=x+1; else r=x-1; } ans=max(ans,cw(st[l],i)); } } calc(L,mid);ans=pa; calc(mid+1,R); return; } void cblc(ll L,ll R){ if(L==R){ for(ll i=0;i<q[L].size();i++){ ll x=q[L][i],tmp; prt[x]=max(ans-w[x]+a[L]-s[n],prt[x]); } while(top>1&&xlr(st[top-1],st[top],L)>=0)top--; st[++top]=L; return; } ll mid=(L+R)>>1,pa=ans; if(top){ for(ll i=L;i<=mid;i++){ ll l=1,r=top-1; while(l<=r){ ll x=(l+r)>>1; if(cw(i,st[x])<=cw(i,st[x+1]))l=x+1; else r=x-1; } ans=max(ans,cw(i,st[l])); } } cblc(mid+1,R);ans=pa; cblc(L,mid); return; } signed main() { freopen("score.in","r",stdin); freopen("score.out","w",stdout); scanf("%lld",&n); for(ll i=1;i<=n;i++) scanf("%lld",&a[n-i+1]); for(ll i=1;i<=n;i++)s[i]=s[i-1]+a[i]; solve(0,n,g); for(ll i=1;i<n-i+1;i++) swap(a[i],a[n-i+1]),swap(g[i],g[n-i+1]); for(ll i=1;i<=n;i++)s[i]=s[i-1]+a[i]; solve(0,n,f); scanf("%lld",&m); for(ll i=1;i<=m;i++){ ll x; scanf("%lld%lld",&x,&w[i]); q[x].push_back(i); } suf[n+2]=-inf; for(ll i=n+1;i>=1;i--) suf[i]=max(suf[i+1],g[i]+s[i-1]); for(ll i=0,pre=-inf;i<=n;i++){ for(ll j=0;j<q[i].size();j++){ ll x=q[i][j]; prt[x]=suf[i+1]+pre-s[n]; } pre=max(pre,f[i]-s[i]); } ans=-inf;top=0; for(ll i=1;i<=n;i++)yf[i]=f[i]*2+i*i+i;calc(0,n+1); ans=-inf;top=0; for(ll i=1;i<=n;i++)yf[i]=g[i]*2+(n-i+1)*(n-i+1)+(n-i+1); cblc(0,n+1); for(ll i=1;i<=m;i++) printf("%lld\n",max(prt[i],0ll)); return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/14412512.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(59)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示