JZOJ1609 幻灯片 离散化+模拟

本文介绍了一种解决JZOJ1609幻灯片问题的方法,通过离散化优化数据范围,将坐标之间的相对大小关系作为重点,避免了因坐标值大导致的暴力解法效率低下,从而在100%的数据情况下获得正确答案。
摘要由CSDN通过智能技术生成

https://jzoj.net/junior/#main/show/1609

 

数据说明:

对于50%的数据,0<=X1,Y1,X2,Y2<=10^2。

对于100%的数据,0<=X1,Y1,X2,Y2<=10^9。

此题直接暴力只能得50分,通过观察100%数据可看出,虽然坐标的范围达到10^9,但数量N ≤ 100,即x,y坐标最多200个,根据题意可看出,我们并不需要关心坐标本身的大小,而是坐标之间的相对大小关系,所以此题可以使用离散化优化数据范围,再使用暴力模拟即可。

 

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100;
int n,tot1,tot2,cnt1 = 0,cnt2 = 0,res = 0;
int set[N + 100][6],_x[2 * N + 100],_y[2 * N + 100],maze[2 * N + 10][2 * N + 10],ans[N * N + 100];
//                   储存x1,x2 排序、去重            离散化后的涂色地图         桶,统计颜色出现次数 
/*void write1(){
	for(int i = 1;i <= n;i++)
		printf("%d %d %d %d %d\n",set[i][1],set[i][2],set[i][3],set[i][4],set[i][5]);
	printf("\n\n\n");
}
void write2(){
	for(int i = 1;i <= 2 * n;i++){
		for(int j = 1;j <= 2 * n;j++)
			printf("%d ",maze[i][j]);
		printf("\n");
	}
	printf("\n\n\n");
}*/
void solve(){//暴力涂色 统计颜色总数 
	for(int i = 1;i <= n;i++)
		for(int j = set[i][1] + 1;j <= set[i][3];j++)
			for(int k = set[i][2] + 1;k <= set[i][4];k++)
				maze[j][k] += set[i][5];
	for(int i = 1;i <= 2 * n;i++)
		for(int j = 1;j <= 2 * n;j++)
			if(maze[i][j] > 0)
			 	ans[maze[i][j]]++;
	for(int i = 1;i <= 10000;i++)
		if(ans[i] > 0)
			res++;
}
void lsh(){//离散化 对于只关心数据间相对大小的题目 进行数据规模的缩减 
	sort(_x + 1,_x + cnt1 + 1);
	sort(_y + 1,_y + cnt2 + 1);
	tot1 = unique(_x + 1,_x + cnt1 + 1) - _x - 1;//去重 
	tot2 = unique(_y + 1,_y + cnt2 + 1) - _y - 1;
	for(int i = 1;i <= n;i++){
		set[i][1] = lower_bound(_x + 1,_x + tot1 + 1,set[i][1]) - _x;//用序号替换原数 
		set[i][2] = lower_bound(_y + 1,_y + tot2 + 1,set[i][2]) - _y;
		set[i][3] = lower_bound(_x + 1,_x + tot1 + 1,set[i][3]) - _x;
		set[i][4] = lower_bound(_y + 1,_y + tot2 + 1,set[i][4]) - _y;
	}
}
int main()
{
	scanf("%d",&n);
	memset(ans,0,sizeof ans);
	memset(maze,0,sizeof maze);
	for(int i = 1;i <= n;i++){
		scanf("%d%d%d%d%d",&set[i][1],&set[i][2],&set[i][3],&set[i][4],&set[i][5]);
		_x[++cnt1] = set[i][1];
		_x[++cnt1] = set[i][3];
		_y[++cnt2] = set[i][2];
		_y[++cnt2] = set[i][4];
	}
	lsh();
	solve();
	//write1();
	//write2();
	printf("%d",res);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值