CF1648D Serious Business 题解
题目链接
题目解法
先考虑朴素的
不难发现有两个断点 是重要的,即 在第 行, 在第 行, 在第 行
不妨枚举断点 ,然后统计最优的
令 表示断点在 的最大收益(只计算第 行和第 行)
答案即为
考虑转移,枚举 被覆盖的区间,假设为 :
- 只用当前区间覆盖
- 同时用其他区间覆盖
不难发现,最优的情况一定是
发现 是定值,可以移出转移
考虑线段树优化
情况 是好优化的,直接在 时枚举区间,然后线段树上区间求 即可
情况 比较复杂,我们考虑在 处记录结果(因为要满足 的限制),然后从前往后更新后缀即可,有些难懂
需要记录的东西有区间 ,区间 ,和下传的
时间复杂度
#include <bits/stdc++.h> #define F(i,x,y) for(int i=(x);i<=(y);i++) #define DF(i,x,y) for(int i=(x);i>=(y);i--) #define ms(x,y) memset(x,y,sizeof(x)) #define SZ(x) (int)x.size()-1 #define pb push_back using namespace std; typedef long long LL; typedef unsigned long long ull; typedef pair<int,int> pii; template<typename T> void chkmax(T &x,T y){ x=max(x,y);} template<typename T> void chkmin(T &x,T y){ x=min(x,y);} inline int read(){ int FF=0,RR=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1; for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48; return FF*RR; } typedef long long LL; const int N=500100; const LL inf=1e15; int n,m,a[3][N]; LL f[N],s[3][N]; vector<pii> cost[N]; struct Sgt1{ LL seg[N<<2]; void clear(){ F(i,1,n<<2) seg[i]=-inf;} void modify(int l,int r,int x,int L,int R,LL val){ if(L<=l&&r<=R){ chkmax(seg[x],val);return;} int mid=(l+r)>>1; if(mid>=L) modify(l,mid,x<<1,L,R,val); if(mid<R) modify(mid+1,r,x<<1^1,L,R,val); } LL query(int l,int r,int x,int pos){ if(l==r) return seg[x]; int mid=(l+r)>>1; if(mid>=pos) return max(query(l,mid,x<<1,pos),seg[x]); else return max(query(mid+1,r,x<<1^1,pos),seg[x]); } }sg1; struct Sgt2{ LL seg[N<<2],rec[N<<2],mink[N<<2]; void clear(){ F(i,1,n<<2) seg[i]=-inf,rec[i]=-inf,mink[i]=inf;} void pushdown(int x){ if(rec[x]!=-inf){ chkmax(seg[x<<1],rec[x]-mink[x<<1]),chkmax(seg[x<<1^1],rec[x]-mink[x<<1^1]); chkmax(rec[x<<1],rec[x]),chkmax(rec[x<<1^1],rec[x]); rec[x]=-inf; } } void modify(int l,int r,int x,int pos,LL v,LL k){ if(l==r){ chkmax(seg[x],v),chkmin(mink[x],k);return;} pushdown(x); int mid=(l+r)>>1; if(mid>=pos) modify(l,mid,x<<1,pos,v,k); else modify(mid+1,r,x<<1^1,pos,v,k); seg[x]=max(seg[x<<1],seg[x<<1^1]); mink[x]=min(mink[x<<1],mink[x<<1^1]); } void update(int l,int r,int x,int lb,LL val){ if(r<lb) return; if(l>=lb){ chkmax(seg[x],val-mink[x]),chkmax(rec[x],val);return;} pushdown(x); int mid=(l+r)>>1; update(l,mid,x<<1,lb,val),update(mid+1,r,x<<1^1,lb,val); seg[x]=max(seg[x<<1],seg[x<<1^1]); } LL query(int l,int r,int x,int lb){ if(r<lb) return -inf; if(l>=lb) return seg[x]; pushdown(x); int mid=(l+r)>>1; return max(query(l,mid,x<<1,lb),query(mid+1,r,x<<1^1,lb)); } }sg2; int main(){ n=read(),m=read(); F(i,0,2) F(j,1,n) a[i][j]=read(); F(i,1,m){ int l=read(),r=read(),k=read(); cost[l].pb({r,k}); } F(i,0,2) F(j,1,n) s[i][j]=s[i][j-1]+a[i][j]; F(i,0,n) f[i]=-inf; sg1.clear(),sg2.clear(); F(i,1,n){ for(auto [r,k]:cost[i]) sg2.modify(1,n,1,r,s[0][i]-s[1][i-1]-k,k),sg1.modify(1,n,1,i,r,f[i-1]-k); sg2.update(1,n,1,i,s[0][i]-s[1][i-1]); f[i]=max(sg1.query(1,n,1,i),sg2.query(1,n,1,i)); } LL ans=-inf; F(i,1,n) chkmax(ans,s[2][n]-s[2][i-1]+f[i]+s[1][i]); printf("%lld\n",ans); fprintf(stderr,"%d ms\n",int(1e3*clock()/CLOCKS_PER_SEC)); return 0; }
标签:
Codeforces
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】