幻 灯 片 幻灯片 幻灯片
题目链接:jzoj 1609
题目大意
有n个幻灯片映在一起,每个幻灯片的的左上角是a1,a2,右上角是a3,a4,颜色是a5当多个幻灯片在同一个位置时,那个位置的颜色就是他们的和,求有多少种颜色。
样例输入
3
2 2 3 3 2
2 0 4 4 1
1 1 3 5 3
样例输出
4
数据范围
对于
50
%
50%
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
%
100%
100%的数据,
0
<
=
X
1
,
Y
1
,
X
2
,
Y
2
<
=
1
0
9
;
1
<
=
N
<
=
100
0<=X1,Y1,X2,Y2<=10^9;1<=N<=100
0<=X1,Y1,X2,Y2<=109;1<=N<=100。
思路
这道题要用到离散化和差分。
不过一开始,为了处理两个幻灯片粘着却不重合的特殊情况,我们要做一些处理(幻灯片的边加
0.5
0.5
0.5或减
0.5
0.5
0.5)。
接着,我们要离散化。离散化之前,要排序和去重,还要把去重后的坐标放回原位。
然后,我们可以用差分,推出每一个地方的颜色。我们在推的过程中,可以统计出颜色的个数了。
代码
#include<cstdio>
#include<algorithm>
using namespace std;
struct note
{
int x1,y1,x2,y2,c;
}a[101];
int n,b[801],k,l,f[1001][1001],ans;
bool in[10001];
int main()
{
// freopen("b.in","r",stdin);
// freopen("b.out","w",stdout);
scanf("%d",&n);//读入
for (int i=1;i<=n;i++)
{
scanf("%d%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2,&a[i].c);//读入
b[++k]=a[i].x1-0.5;//去除粘着却不重合的情况
b[++k]=a[i].y1-0.5;
b[++k]=a[i].x2+0.5;
b[++k]=a[i].y2+0.5;
b[++k]=a[i].x1+=0.5;
b[++k]=a[i].y1+=0.5;
b[++k]=a[i].x2-=0.5;
b[++k]=a[i].y2-=0.5;
}
sort(b+1,b+k+1);//排序
l=unique(b+1,b+k+1)-b-1;//去重
for (int i=1;i<=n;i++)
{
a[i].x1=lower_bound(b+1,b+l+1,a[i].x1)-b;//离散化
a[i].y1=lower_bound(b+1,b+l+1,a[i].y1)-b;
a[i].x2=lower_bound(b+1,b+l+1,a[i].x2)-b;
a[i].y2=lower_bound(b+1,b+l+1,a[i].y2)-b;
//四个角
f[a[i].x1][a[i].y1]+=a[i].c;//左上角
f[a[i].x2+1][a[i].y2+1]+=a[i].c;//右下角
f[a[i].x1][a[i].y2+1]-=a[i].c;//右上角
f[a[i].x2+1][a[i].y1]-=a[i].c;//左下角
}
for (int i=1;i<=l;i++)
for (int j=1;j<=l;j++)
{
f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];//差分
if (f[i][j]&&!in[f[i][j]])//如果有颜色且颜色没标记过
{
in[f[i][j]]=1;//标记
ans++;//颜色数加一
}
}
printf("%d",ans);//输出颜色数
// fclose(stdin);
// fclose(stdout);
return 0;
}