题意:
给你n个矩形,你现在可以添加两个矩形,使得被k个矩形覆盖的面积最大。
题解:
这两个新加入的矩形要么是互为上下或者互为左右的关系,那么我们要处理出来第i行上面最大的情况和第i行下面最大的情况,第i列左边最大的情况和第i列右边的最大的情况。那么我们怎么维护最大值?我们可以先用二维前缀和求出200*200区间的所有覆盖情况,然后将k-1置为1,k置为-1,其它置为0,再自底向上求一个前缀和,这样的话我们枚举上下区间做区间最大子矩阵的时候就会方便一点,同时维护4个数组的值,最后for一遍求最大值。
#include<bits/stdc++.h>
using namespace std;
int up[205],down[205],lef[205],rig[205];
int mp[205][205];
int main()
{
int n,k,l,r,u,d;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d%d%d%d",&l,&d,&r,&u),mp[l][d]++,mp[r][d]--,mp[l][u]--,mp[r][u]++;
for(int i=0;i<=200;i++)
for(int j=0;j<=200;j++)
if(i>0)
mp[i][j]+=mp[i-1][j];
int ans=0;
for(int i=0;i<=200;i++)
{
for(int j=0;j<=200;j++)
{
if(j>0)
mp[i][j]+=mp[i][j-1];
ans=ans+(mp[i][j]==k?1:0);
}
}
for(int i=0;i<200;i++)
{
for(int j=0;j<200;j++)
{
if(mp[i][j]==k)
mp[i][j]=-1;
else if(mp[i][j]==k-1)
mp[i][j]=1;
else
mp[i][j]=0;
}
}
int mx=0;
int val[205]={0};
for(d=0;d<200;d++)
{
for(int i=0;i<200;i++)
val[i]=0;
for(u=d;u<200;u++)
{
mx=0;
for(int i=0;i<200;i++)
val[i]+=mp[i][u];
for(int i=0;i<200;i++)
{
mx=max(0,mx+val[i]);
up[d]=max(up[d],mx);
down[u]=max(down[u],mx);
}
}
}
for(l=0;l<200;l++)
{
for(int i=0;i<200;i++)
val[i]=0;
for(r=l;r<200;r++)
{
mx=0;
for(int i=0;i<200;i++)
val[i]+=mp[r][i];
for(int i=0;i<200;i++)
{
mx=max(0,mx+val[i]);
rig[l]=max(rig[l],mx);
lef[r]=max(lef[r],mx);
}
}
}
mx=0;
for(int i=1;i<200;i++)
lef[i]=max(lef[i],lef[i-1]),down[i]=max(down[i],down[i-1]);
for(int i=200-1;i>=0;i--)
rig[i]=max(rig[i],rig[i+1]),up[i]=max(up[i],up[i+1]);
for(int i=1;i<=200;i++)
mx=max(mx,lef[i-1]+rig[i]),mx=max(mx,up[i]+down[i-1]);
printf("%d\n",ans+mx);
return 0;
}