题目大意:
有一面海报墙,在墙上顺序贴n张海报(海报的高度与墙的高度一样高),墙上有刻度,给出每张海报对应的起始刻度和终止刻度,求最后能看到的海报的数目。
解题思路:
线段覆盖的问题,想到用线段树来做。但是由于此题的数据范围太大,需要使用离散化,这里就是把每张海报的起始刻度和终止刻度离散到里一个数组里边,输入的时候海报的刻度信息是存在一个结构体的数组里边,通过离散化的方式,存在了一个连续的一维数组里边。(如果不是很清楚的话,可以通过单步调试的方法,加深理解。)
AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 20002
struct poster//海报结构题
{
};
poster p[N/2];//存储海报信息的结构题数组
int index[N];//离散化后的海报信息存储数组
int part[N];//存储墙上露在外边的海报的编号(一种海报用一个编号标记)
int li_num;//离散后,有多少个不同的起始终止位置
bool see[N/2];//最后用于判断每种海报是否被数过的标记数组
int index[N];//离散化后的海报信息存储数组
int part[N];//存储墙上露在外边的海报的编号(一种海报用一个编号标记)
int li_num;//离散后,有多少个不同的起始终止位置
bool see[N/2];//最后用于判断每种海报是否被数过的标记数组
int find(int k)//查找k这个刻度在离散化数组里边的下标
{
for(int i=0;i<li_num;i++)
{
if(index[i]==k)return i;
}
return 0;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.txt","r",stdin);
#endif
int ca;
//while(cin>>ca)
while((scanf("%d",&ca))==1)//使用scanf,一开始用cin超时
{
while(ca--)
{
int n;
scanf("%d",&n);//cin>>n;
for(int i=0;i<n;i++)
{
//cin>>p[i].start>>p[i].end;
scanf("%d%d",&p[i].start,&p[i].end);
index[2*i]=p[i].start;//离散化处理
index[2*i+1]=p[i].end;
}
int kn=2*n;
sort(index,index+kn);//对刻度进行排序
li_num=0;
for(int i=1;i<kn;i++)
{
if(index[i]!=index[i-1])//忽略相同的刻度
index[li_num++]=index[i-1];
part[i]=-1;//把墙上每个刻度一开始的海报标记为-1
}
index[li_num++]=index[kn-1];
for(int i=0;i<n;i++)
{
int s=find(p[i].start);
int e=find(p[i].end);
for(int j=s;j<=e;j++)
{
part[j]=i;//按照顺序标记墙上海报的标号
}
}
memset(see,false,sizeof(see));//初始化see数组
int ans=0;
for(int i=0;i<li_num;i++)
{
if(!see[part[i]])
{
ans++;//如果编号为part[i]的海报没有数过,就数一次
see[part[i]]=true;//标记已经输过了
}
}
cout<<ans<<endl;
}
}
}
{
}
int main()
{
#ifndef ONLINE_JUDGE
#endif
}