1 条题解
-
0
自动搬运
来自洛谷,原作者为

Time_tears
oi复健ing搬运于
2025-08-24 22:17:25,当前版本为作者最后更新于2020-09-04 15:53:50,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
提供一篇 的题解
-
首先看完本题,一定知道直接对每个位置加 是绝对没有出路的,所以我们首先需要用一个差分处理一下每个位置的值,这部分复杂度是 的。
-
然后,我们要想,什么样的位置会对 有影响呢 当然是值为 的位置,首先我们用一个 记录下值为 的位置数量。然后我们就发现,给区间加 后,值为 的位置贡献为 ,值为 的贡献为 ,然后我们枚举 把第 至 的数给提出来,用一次最大连续子段和,这样就能求出以 为右下节点的最大的值,再反过来做一次,就能求出以 为左上节点的最大的值
-
因为是求两个区间,所以最后再用一次 dp 即可。
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize("Ofast") #pragma GCC optimize("inline") #include<cstdio> #define N 205 using namespace std; int k,e[N][N],f[N][N],d[N][N],ans; int n,a[N][N],b[N][N],c[N][N],sum; const int Mxdt=200000; inline char gc() { static char buf[Mxdt],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,Mxdt,stdin),p1==p2)?EOF:*p1++; } inline int read() { int res=0,bj=0; char ch=gc(); while(ch<'0'||ch>'9')bj|=(ch=='-'),ch=gc(); while(ch>='0'&&ch<='9')res=(res<<3)+(res<<1)+(ch^48),ch=gc(); return bj?-res:res; } inline int max(int x,int y) { return x>y?x:y; } int main() { n=read(),k=read(); for(int i=1,x1,y1,x2,y2; i<=n; ++i)++a[x1=read()+1][y1=read()+1],++a[x2=read()+1][y2=read()+1],--a[x1][y2],--a[x2][y1]; for(int i=1; i<=200; ++i) for(int j=1; j<=200; ++j) { a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1],b[i][j]=b[i][j-1]; if(a[i][j]==k)--b[i][j],++sum; if(a[i][j]==k-1)++b[i][j]; } for(int i=1; i<=200; ++i) for(int j=i; j<=200; ++j) { for(int k=1,len=0; k<=200; ++k)c[k][j]=max(c[k][j],len=max(0,len)+b[k][j]-b[k][i-1]); for(int k=200,len=0; k; --k)d[k][i]=max(d[k][i],len=max(0,len)+b[k][j]-b[k][i-1]); } for(int i=200; i; --i) for(int j=200; j; --j)f[i][j]=max(max(f[i+1][j],f[i][j+1]),d[i][j]); for(int i=1; i<=200; ++i) for(int j=1; j<=200; ++j)e[i][j]=max(max(e[i-1][j],e[i][j-1]),c[i][j]),ans=max(ans,sum+e[i][j]+max(f[i+1][1],f[1][j+1])); printf("%d",ans); return 0; } -
- 1
信息
- ID
- 5130
- 时间
- 2000ms
- 内存
- 250MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者