离散化:把无限空间中有限的个体映射到有限的空间中去,以此来提高算法的时空效率。
基本思想:在众多的可能的情况中“中考虑我需要的值”。
大致题意:在一面墙上贴海报,可覆盖,求最终露出来的海报的个数。
由于数据范围较大,所以想到离散化,把数据进行排序,在排序之后将下标号作为新的数值进行计算,之后就利用线段树。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAX 20010
int c,n;
struct node//线段树的结构
{
int l,r;
int c;
}tree[MAX*4];
struct In//用于离散化
{
int li,num;//num表示第几张海报
}line[MAX];
int set[MAX][2];//起点和终点
bool visit[MAX];
int ans;
bool cmp(struct In a,struct In b)
{
return a.li<b.li;
}
void Inittree(int pos,int ll,int rr)//建立线段树(模板)
{
tree[pos].l=ll;
tree[pos].r=rr;
tree[pos].c=0;
if(ll!=rr)
{
int mid=(ll+rr)>>1;
Inittree(pos*2,ll,mid);
Inittree(pos*2+1,mid+1,rr);
}
}
void Insert(int pos,int ll,int rr,int color)//更新树 主要是tree[i].c
{
if(tree[pos].l==ll&&tree[pos].r==rr)
{
tree[pos].c=color;
return;
}
if(tree[pos].c>0&&tree[pos].c!=color)//处理被覆盖的情况
{
tree[pos*2].c=tree[pos].c;
tree[pos*2+1].c=tree[pos].c;
tree[pos].c=0;
}
int mid=(tree[pos].l+tree[pos].r)>>1;
if(rr<=mid)
{
Insert(pos*2,ll,rr,color);
}
else if(mid<ll)
{
Insert(pos*2+1,ll,rr,color);
}
else
{
Insert(pos*2,ll,mid,color);
Insert(pos*2+1,mid+1,rr,color);
}
}
void Search(int pos)//结果求解
{
if(tree[pos].c!=0)
{
if(!visit[tree[pos].c])
{
visit[tree[pos].c]=true;
ans++;
}
return;
}
Search(2*pos);
Search(2*pos+1);
}
int main()
{
int i;
while(scanf("%d",&c)!=EOF)
{
while(c--)
{
scanf("%d",&n);
for(i=0;i<n;i++)//离散化
{
scanf("%d%d",&set[i][0],&set[i][1]);
line[2*i].li=set[i][0];
line[2*i].num=-(i+1);
line[2*i+1].li=set[i][1];
line[2*i+1].num=i+1;
}
sort(line,line+2*n,cmp);
int temp=line[0].li,tp=1;
for(i=0;i<2*n;i++)//离散化
{
if(line[i].li!=temp)
{
tp++;
temp=line[i].li;
}
if(line[i].num<0)
{
set[-line[i].num-1][0]=tp;
}
else
{
set[line[i].num-1][1]=tp;
}
}
Inittree(1,1,tp);
for(i=0;i<n;i++)//更新树
{
Insert(1,set[i][0],set[i][1],i+1);
}
memset(visit,false,sizeof(visit));
ans=0;
Search(1);
printf("%d\n",ans);
}
}
return 0;
}