Description
Farmer John 不太擅长多任务处理。他经常分心,很难完成一些长期的项目。目前,他正在谷仓的一侧刷油漆,但他一直忙着在很小的区域涂抹油漆,然后由于抚育母牛的需要而陷入困境,使谷仓的某些部分比其他部分涂有更多的油漆。
我们将谷仓的墙描述为一个 X-Y 平面,每次涂油漆的区域都是一个矩形。FJ 在这个平面上绘制了 N 个矩形,每个矩形的边均与坐标轴平行。因此我们用矩形的左下角和右上角坐标来描述一个矩形。
FJ 想在谷仓里涂几层油漆,这样就不需要在不久的将来再次重新涂油漆。但是,他不想浪费时间涂过多的油漆。事实证明,K 层涂料是最佳用量。但是因为涂油漆的面积太小了,FJ 并不太高兴。他决定最多再绘制两个不相交的矩形(这里的相交指两个矩形交的面积大于零,即如果两个矩形仅共用一条边或一个点,则不视为相交)来增加面积。当然不绘制新矩形或仅绘制一个新矩形也是允许的。
Input
第一行两个整数 N,K(1≤N,K≤10^5)。
接下来 NN 行,每行四个整数 x1,y1,x2,y2(0≤x1,y1,x2,y2≤200),描述一个矩形。其左下角坐标为(x1,y1),右上角坐标为x2,y2。保证所有矩形面积为正,即其不会退化为线段或点。
和现有的矩形一样,新绘制的矩形,其左下角和右上角坐标也必须是整数,且坐标必须在0∼200 之间,面积也必须为正。
Output
输出被涂油漆恰好 K 次区域的最大面积。
Sample Input
3 2
1 1 4 4
3 3 7 6
2 2 8 7
Sample Output
26
Data Constraint
首先考虑如何画出整张地图:差分一下,等于k-1的就把权值设为1,等于k的设为-1,并且令ans+1
先考虑一维,一个区间怎么做
这是一个很经典的问题,从前往后扫,不停累加,直到负数就清0,记录最大值即可
考虑二维一个矩阵。由于只有200,所以我们可以枚举上边界和下边界。然后每列做一个前缀和,就和一维一样了
考虑题目的问题。发现这两个矩阵要么以一行为分割线,分布于上下,要么以一列为分割线,分布于左右。那你从左往右做,然后从右往左做,就可以解决左右的。上下同理
#include
#define left hafhdioiq
#define right quyuq
#define up qweryai
#define down fuck
using namespace std;
const int N=1e5+5;
int x[N][2],y[N][2],d[277][277],sum[277][277],left[277],right[277],up[277],down[277];
int main()
{
freopen("paintbarn.in","r",stdin); freopen("paintbarn.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
{
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2); x1++,x2++,y1++,y2++;
d[x1][y1]++; d[x2][y2]++; d[x1][y2]--; d[x2][y1]--;
}
int yjy=0;
for(int i=1; i<=201; i++) for(int j=1; j<=201; j++)
{
d[i][j]+=d[i-1][j]+d[i][j-1]-d[i-1][j-1];
if(d[i][j]==m) yjy++;
}
for(int i=1; i<=200; i++) for(int j=1; j<=200; j++)
{
int to=0;
if(d[i][j]==m)to=-1;
if(d[i][j]==m-1)to=1;
d[i][j]=to;
}
int aii=0;
memset(sum,0,sizeof sum);
for(int i=1; i<=200; i++) for(int j=1; j<=200; j++) sum[i][j]=d[i][j]+sum[i-1][j];
for(int i=1; i<=200; i++) for(int j=i; j<=200; j++)
{
int dp;
for(int k=1; k<=200; k++)
{
int s=sum[j][k]-sum[i-1][k];
if(k==1)dp=s;
else dp=max(s,dp+s);
up[j]=max(up[j],dp);
down[i]=max(down[i],dp);
aii=max(aii,dp);
}
}
memset(sum,0,sizeof sum);
for(int i=1; i<=200; i++) for(int j=1; j<=200; j++) sum[i][j]=d[i][j]+sum[i][j-1];
for(int i=1; i<=200; i++) for(int j=i; j<=200; j++)
{
int dp;
for(int k=1; k<=200; k++)
{
int s=sum[k][j]-sum[k][i-1];
if(k==1)dp=s;
else dp=max(s,dp+s);
left[j]=max(left[j],dp);
right[i]=max(right[i],dp);
aii=max(aii,dp);
}
}
for(int i=1; i<=200; i++)
{
left[i]=max(left[i],left[i-1]);
up[i]=max(up[i],up[i-1]);
}
for(int i=200; i>=1; i--)
{
right[i]=max(right[i],right[i+1]);
down[i]=max(down[i],down[i+1]);
}
for(int i=1; i<=199; i++)
{
aii=max(aii,left[i]+right[i+1]);
aii=max(aii,up[i]+down[i+1]);
}
printf("%d",yjy+aii);
}