zoj 3528 Parterre

19 篇文章 0 订阅

很多人说这个可以暴力水过去的= =。。可见数据好弱。。

不过还是没有放弃我的那个做法,虽然WA掉好多次。。。

又看了下题,暴力和暴力程序对拍,也没发现BUG。。。后来一想,可能是理解问题了,我理解的花花的颜色是不可以重复的 = =。。。人家题目木有说不重复!!!

好吧,改了,A之。。。

我的做法是,统计在框框里的四条线段的长度,枚举每一个框框,如果框框退化为一条线段或者一个点,特判。

先计算出来四个角在询问框框里的数目,后续计算需要。具体细节不多说了,好好想想就可以的。

#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define FOR(i,s,t) for(int i=s; i<t; i++)
#define BUG puts("here!!!")

using namespace std;

const int MAX = 600;
struct point {
	int x,y;
	void P(int xx, int yy)
	{
		x = xx; y = yy;
	}
};
bool operator==(point a, point b) { return a.x == b.x && a.y == b.y; }
struct NODE{ point p[4]; int ind;};
NODE node[MAX];

bool in(point a, point l1, point l2)
{
	return a.x <= l2.x && a.x >= l1.x 
		&& a.y >= l1.y && a.y <= l2.y;
}

int solve(point *p, point a, point b, point c, point d)
{
	int sum = 0;
	if( p[0].x >= a.x && p[0].x <= d.x )
	{
		int y1 = max(p[0].y, a.y);
		int y2 = min(p[1].y, b.y);
		if( y2 >= y1 )
			sum += y2 - y1 + 1;
	}

	if( p[1].y >= a.y && p[1].y <= b.y )
	{
		int x1 = max(p[1].x, a.x);
		int x2 = min(p[2].x, d.x);
		if( x2 >= x1 )
			sum += x2 - x1 + 1;
	}
	
	if( p[3].x >= a.x && p[3].x <= d.x )
	{
		int y1 = max(p[3].y, a.y);
		int y2 = min(p[2].y, b.y);
		if( y2 >= y1 )
			sum += y2 - y1 + 1;
	}
	
	if( p[0].y >= a.y && p[0].y <= b.y )
	{
		int x1 = max(p[0].x, a.x);
		int x2 = min(p[3].x, d.x);
		if( x2 >= x1 )
			sum += x2 - x1 + 1;
	}
	
	return sum;
}

int compute(int sum, int cc, point *p)
{
	if( p[0] == p[1] && p[1] == p[2] && p[2] == p[3] )
		return sum/4;
	if( p[0] == p[1] || p[1] == p[2] )
		return (sum - cc/2)/2;
	return sum - cc;
}
int num[MAX];
int main()
{
	int n, m, ind, q;
	while( ~scanf("%d%d", &n, &m) )
	{
		int p = min((n+1)/2, (m+1)/2);
		point s, t;
		s.P(0, 0);
		t.P(n-1, m-1);

		FOR(i, 0, p)
		{
			scanf("%d", &ind);
			node[i].ind = ind;
			node[i].p[0].P(s.x + i, s.y + i);
			node[i].p[1].P(s.x + i, t.y - i);
			node[i].p[2].P(t.x - i, t.y - i);
			node[i].p[3].P(t.x - i, s.y + i);
		}
		
		scanf("%d", &q);
		
		point a, b, c, d;
		while( q-- )
		{
			int maxsum = 0, cnt = 0, tmp;
			memset(num, 0, sizeof(num));
			
			scanf("%d%d%d%d", &a.x, &a.y, &c.x, &c.y);

			point b, d;
			b.P(a.x, c.y);
			d.P(c.x, a.y);
			
			FOR(i, 0, p)
			{

				int cc = 0;
				FOR(k, 0, 4)
					if( in(node[i].p[k], a, c) )
						cc++;

				int sum = solve(node[i].p, a, b, c, d);
				sum = compute(sum, cc, node[i].p);
				
				if( !num[node[i].ind] && sum != 0 )
					cnt++;
				num[node[i].ind] += sum;
				sum = num[node[i].ind];
				
				if( sum >= maxsum )
				{
					if( sum > maxsum || sum == maxsum && tmp > node[i].ind )
						tmp = node[i].ind;
					maxsum = sum;
				}
			}
			printf("%d %d %d\n",cnt, tmp, maxsum);	
		}	
		
	}

return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值