矩形

【问题描述】

因为对polo忍无可忍, dzf使用圣剑在地上划出了许多纵横交错的沟壑来泄愤。这些沟壑都严格与X轴平行或垂直。 polo嘲笑了dzf无聊的行为,然后做了一件更加无聊的事。他蹲下来数这些沟壑的条数。数着数着,polo意识到一个问题,那就是因为圣剑的威力太大,划出的沟壑太多,地面就会塌陷。而如果两条水平的沟壑和两条垂直的沟壑相交组成了一个矩形,那么塌陷的危险就会进一步增加。现在polo已经数了n条沟壑,他想知道这些沟壑组成了多少个矩形。

【输入】

第一行一个数n,接下来每行4个数x1,y1,x2,y2,表示沟壑的两个端点(x1,y1),(x2,y2)

【输出】

一个数,组成的矩形个数。

【输入输出样例1】

rect.in

4

0 0 1 0

0 0 0 1

1 1 1 -1

1 1 0 1

rect.out

1

【输入输出样例2】

rect.in

8

1 0 4 0

2 1 2 0

0 0 0 3

2 2 2 3

3 3 3 -1

0 3 4 3

4 1 -1 1

3 2 -1 2

rect.out

6

【数据说明】

对于30%的数据,1<=n<=100

对于60%的数据,1<=n<=600

对于100%的数据,1<=n<=2000,坐标绝对值小于10^9,任意两条与X轴水平的沟壑之间没有交点,任意两条与X轴垂直的沟壑没有交点。

题解:

30分四重循环,60分三重循环,100分是线段树+离散化?? 
目前100分有些困难,线段树还好,离散化还没有学到,以后懂了再来解决吧
那么这份代码是60分做法,即枚举两条竖线(或者横线)和一条横线(或竖线)
首先把横竖线分开存,并且我们存的时候要保证x1和y1为较小的坐标,方便我们后面判断两条线段是否相交
后面三层循环枚举边,先确定两条竖线,然后再在所有横线里面找与这两条竖线都相交的有多少条
显然,从这些相交的横线中随意选择不同的两条即可组成一个矩形,那么对于这一次,
就有C(k,2)种矩形组合(k为相交条数),对于这个式子我们化简得到k*(k-1)/2,否则直接套用公式的话明显会爆掉

每一次累加答案,时间复杂度为O(n^3),可以得60分

代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<stack>
#include<queue>
#define MAXA 200005
using namespace std;
int n,cnt_Heng,cnt_Shu,Cross;
long long Ans;
struct RX {
	int x1,y1;
	int x2,y2;
}Heng[MAXA],Shu[MAXA];
int main() {
//	freopen("rect.in","r",stdin);
//	freopen("rect.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);
	
	cin >> n;
	for(int i=1;i<=n;i++) {
		int t1 = 0,t2 = 0,t3 = 0,t4 = 0;
		cin >> t1 >> t2 >> t3 >> t4;
		if(t2 == t4) {
			Heng[++cnt_Heng].x1 = min(t1,t3);
			Heng[cnt_Heng].y1 = t2;
			Heng[cnt_Heng].x2 = max(t1,t3);
			Heng[cnt_Heng].y2 = t4;
		}
		if(t1 == t3) {
			Shu[++cnt_Shu].x1 = t1;
			Shu[cnt_Shu].y1 = min(t2,t4);
			Shu[cnt_Shu].x2 = t3;
			Shu[cnt_Shu].y2 = max(t2,t4);
		}
	}
	if(n < 4) {
		printf("0");
		return 0;
	}
	for(int i=1;i<=cnt_Shu;i++)
	    for(int j=i+1;j<=cnt_Shu;j++) {
	    	Cross = 0;
	    	for(int k=1;k<=cnt_Heng;k++) {
	        	if(Heng[k].x1 <= Shu[i].x1 && Heng[k].x1 <= Shu[j].x1 && Heng[k].x2 >= Shu[i].x1 && Heng[k].x2 >= Shu[j].x1
				&& Heng[k].y1 >= Shu[i].y1 && Heng[k].y1 >= Shu[j].y1 && Heng[k].y1 <= Shu[i].y2 && Heng[k].y1 <= Shu[j].y2)
				   Cross++;
				
			}
			Ans += Cross * (Cross - 1) / 2;
		}
	cout << Ans;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值