在一个平面上放置有许多涂满颜色的幻灯片,这些幻灯片都是矩形而且是半透明的,所有的幻灯片的四边都与X轴或Y轴平行。我们可以给这些幻灯片的颜色编一个号,相同的数字对应相同的颜色。但是这些幻灯片可能会相互重叠,重叠部分的颜色就会混合变成另一种颜色,这个颜色值等于所有重叠幻灯片的颜色值之和。你的任务是找出这个平面上有多少种不同的颜色。
输入第一行为一个整数 N ( 1 < = N < = 100 ) N(1<=N<=100) N(1<=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<X2,Y1<Y2,1<=C<=100,描述了一张幻灯片的情况, ( X 1 , Y 1 ) (X1,Y1) (X1,Y1)为左下角坐标, ( X 2 , Y 2 ) (X2,Y2) (X2,Y2)为右上角坐标,C为幻灯片颜色值。
输出一个整数,为平面上出现的不同颜色的数量。
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};
……………………
其实也不难,那我们回到这一题…
很显然,这题只需要将很大很大的数据进行离散化,然后进行统计就行啦
看看代码吧:
#include
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;
}