【离散思想】 幻灯片

题目描述

在一个平面上放置有许多涂满颜色的幻灯片,这些幻灯片都是矩形而且是半透明的,所有的幻灯片的四边都与X轴或Y轴平行。我们可以给这些幻灯片的颜色编一个号,相同的数字对应相同的颜色。但是这些幻灯片可能会相互重叠,重叠部分的颜色就会混合变成另一种颜色,这个颜色值等于所有重叠幻灯片的颜色值之和。你的任务是找出这个平面上有多少种不同的颜色。

输入输出格式:

输入格式:

输入第一行为一个整数 N ( 1 < = N < = 100 ) N(1<=N<=100) N1<=N<=100,N为平面上幻灯片的数量。接下来 N N N行每行 5 5 5个整数 X 1 , Y 1 , X 2 , Y 2 , C X1, Y1, X2, Y2, C X1,Y1,X2,Y2,C。满足: X 1 < X 2 , Y 1 < Y 2 , 1 < = C < = 100 X1 < X2,Y1 < Y2,1 <= C <= 100 X1<X2Y1<Y21<=C<=100,描述了一张幻灯片的情况, ( X 1 , Y 1 ) (X1,Y1) (X1,Y1)为左下角坐标, ( X 2 , Y 2 ) (X2,Y2) (X2,Y2)为右上角坐标,C为幻灯片颜色值。

输出格式:

输出一个整数,为平面上出现的不同颜色的数量。

输入输出样例

输入样例#1:

3
2 2 3 3 2
2 0 4 4 1
1 1 3 5 3

输出样例#1:

4

提示信息

对于50%的数据, 0 < = X 1 , Y 1 , X 2 , Y 2 < = 1 0 2 0<=X1,Y1,X2,Y2<=10^2 0<=X1,Y1,X2,Y2<=102
对于100%的数据, 0 < = X 1 , Y 1 , X 2 , Y 2 < = 1 0 9 0<=X1,Y1,X2,Y2<=10^9 0<=X1,Y1,X2,Y2<=109

思路

这题一看,题呀,弄一个二维数组暴力统计不就行了吗?结果看到数据,额…貌似不水…

这题数据有 1 0 9 10^9 109这么大,所以我们要用到一个新的东西——离散化!

其实离散化大概就是:

离散化,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。
通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。例如:
原数据:1,999,100000,15;处理后:1,3,4,2;
原数据:{100,200},{20,50000},{1,400};
处理后:{3,4},{2,6},{1,5};
……………………

其实也不难,那我们回到这一题…
很显然,这题只需要将很大很大的数据进行离散化,然后进行统计就行啦
看看代码吧:

AC代码:

#include<bits/stdc++.h>
using namespace std;
struct aty{
    
    
	int bh,hh,sb,zb;//bh是点的编号,hh表示这个点是左下角还是右上角(左下角为1,右上角为2),sb是离散化后的点,zb是最初输入的点 
}a[201],b[201];//a数组存横坐标的信息,b数组存列坐标的信息 
int cmp(aty a,aty b){
    
    
	return a.zb<b.zb;//按坐标大小来排序 
}
int cmp1(aty a,aty b){
    
    
	if(a.bh!=b.bh) return a.bh<b.bh;
	return a.hh<b.hh;
}
set<int >q;
int n,sum,mp[201][201],c[201];
int main(){
    
    
	cin>>n;
	for(int i=1;i<=n;i++){
    
    
		cin>>a[i].zb>>b[i].zb>>a[i+n].zb>>b[i+n].zb>>c[i];
		a[i].bh=a[i+n].bh=b[i].bh=b[i+n].bh=i;//标号 
		a[i].hh=b[i].hh=1;//左下角 
		a[i+n].hh=b[i+n].hh=2;//右上角 
	}
	int t=2*n;
	sort(a+1,a+1+t,cmp);//按照坐标大小排序
	sort(b+1,b+1+t,cmp);//按照坐标大小排序
	for(int i=1;i<=t;i++){
    
    //去重加离散化 
		if(a[i].zb!=a[i-1].zb) a[i].sb=i;//如果两个点不一样就标为i 
		else a[i].sb=a[i-1].sb;//否则两个一样的点也标为一样的坐标 
		if(b[i].zb!=b[i-1].zb) b[i].sb=i;//同上 
		else b[i].sb=b[i-1].sb;//同上 
	}
	sort(a+1,a+1+t,cmp1);//排回以前的顺序(幻灯片从1~n,每张幻灯片内先左下角后右上角)
	sort(b+1,b+1+t,cmp1);//同上 
	
	for(int k=1;k<=t;k+=2){
    
    //枚举幻灯片
		for(int i=a[k].sb+1;i<=a[k+1].sb;i++){
    
    
			for(int j=b[k].sb+1;j<=b[k+1].sb;j++){
    
    //模拟矩阵(+1是因为坐标表示的是点,但我们要染得是格子)
				mp[i][j]+=c[(k+1)/2];//累加颜色
			}
		}
	}
	
	//看看有多少种不同的颜色 
	for(int i=1;i<=t;i++){
    
    
		for(int j=1;j<=t;j++){
    
    
			if(q.find(mp[i][j])==q.end()&&mp[i][j]>0){
    
    //这里用了一个set,find()如果找到了就会返回地址,如果没找到就会返回end() 
				q.insert(mp[i][j]);
				sum++;
			}
		}
	}
	cout<<sum;//输出 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_61360607/article/details/132362297