【JZOJ 省选模拟】Problem 3. Painting the Barn 2

题目

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); 
}

你可能感兴趣的:(【JZOJ 省选模拟】Problem 3. Painting the Barn 2)