【jzoj P7153】Square Pasture G(暴力)

Square Pasture G

题目链接:jzoj P7153

题目大意

平面上有一些点,问你存在多少种点集,使得有一个四边平行于 xy 轴的正方形可以恰好包住这些点。

思路

由于是一个正方形,我们考虑枚举 x 轴的边或 y 轴的边,然后再减去重复计算的。
(枚举就是选两个点,以它们的 x/y 轴差确定正方形的边长)

首先想怎么要去重,就是它们的 x 轴差等于 y 轴差,那这个对于中途每个搞出来的矩阵计算一下就好了。
那考虑怎么搞矩阵,那首先有几个东西。
这个矩阵一定要包含你一开始选的两个点。
如果那两个点另外一维的距离比这一维的答案就不能搞。

然后不难想到可以拿双指针去搞。
可以枚举右边界,然后算出左边界的上下界,然后就不断统计。
然后具体的统计方式可以看代码,主要就是右边界移动,然后看形成的矩阵是否可能,然后把左边界的不断弹掉,弹到符合下一个的下界,然后弹的过程中那些矩阵都要统计。

代码

#include<cstdio>
#include<iostream>
#include<algorithm> 

using namespace std;

struct node {
	int x, y;
}a[201], tmp[201];
int n, ans, tn, two;

bool cmp(node x, node y) {
	if (x.x != y.x) return x.x < y.x;
	return x.y < y.y;
}

int abss(int x) {
	return (x < 0) ? -x : x;
}

bool cmp1(node x, node y) {
	if (x.y != y.y) return x.y < y.y;
	return x.x < y.x;
}

void work() {
	for (int i = 1; i <= n; i++)
		for (int j = i + 1; j <= n; j++) {//枚举上下边界
			int sz = a[j].x - a[i].x;
			if (sz < abss(a[j].y - a[i].y)) continue;
			tn = 0;
			for (int k = i; k <= j; k++) {
				tmp[++tn] = a[k];
			}
			sort(tmp + 1, tmp + tn + 1, cmp1);
			
			int l = 1, r = 0;
			while (l <= tn && tmp[l].y < max(a[i].y, a[j].y) - sz) l++;//一开始移动到合法的位置
			while (r + 1 <= tn && max(a[i].y, a[j].y) > tmp[r + 1].y) r++;
			for (; r <= tn && tmp[r].y <= min(a[i].y, a[j].y) + sz; r++) {
				if (r == 0) continue;
				int lmin = max(max(a[i].y, a[j].y) - sz, tmp[r].y - sz);//搞出左边界可以的范围
				int lmax = min(min(a[i].y, a[j].y), (r + 1 <= tn ? tmp[r + 1].y - sz - 1 : min(a[i].y, a[j].y)));
				
				while (l <= tn && tmp[l].y < lmin) l++;
				if (tmp[r].y >= max(a[i].y, a[j].y) || tmp[r + 1].y != max(a[i].y, a[j].y)) ans++;
				//右边界移动,除了恰好移动不到位置,别的情况都要加贡献
				if (tmp[r].y - tmp[l].y == sz) two++;//去重,如果刚好框柱就是正方形就会计算两遍
				
				while (l + 1 <= tn && tmp[l].y < lmax) {//左边界移动,新的合法情况出现
					ans++; l++;
					if (tmp[r].y - tmp[l].y == sz) two++;
				}
			}
		}
}

int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d %d", &a[i].x, &a[i].y);
	}
	
	ans = n + 1;
	sort(a + 1, a + n + 1, cmp);
	work();
	for (int i = 1; i <= n; i++)//xy轴翻转再来一次
		swap(a[i].x, a[i].y);
	sort(a + 1, a + n + 1, cmp);
	work();
	
	printf("%d", ans - two / 2);//记得去重,因为计算了两次,所以去重的要除二
	
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值