题意:在墙上贴海报。给出每次所贴的区间,问最后能看到几张海报。
思路:线段树,可是所给区间长度最大为1000000,必须离散化处理。
离散化:把全部点按序排列;
去掉反复的点;给间隔大于一的两数之间加入一个数(避免错误);排序;查找出左右区间的位置(即离散化后所相应的数值)
线段树:用模板就可以解决(一个变量名写错。调试了一中午,呜呜~~温温好失败)
AC代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define maxx 10005
int x[maxx<<2],col[maxx<<4],li[maxx],ri[maxx];
bool flag[maxx];
int n,m,ans;
int Bsearch(int key)
{
int left=0,right=m-1,mid;
while(left<=right)
{
mid=(left+right)>>1;
if(x[mid]==key) return mid;
if(x[mid]<key)
left=mid+1;
else
right=mid-1;
}
return -1;
}
void pushdown(int rt)
{
if(col[rt]!=-1)
{
col[rt<<1]=col[rt];
col[rt<<1|1]=col[rt];
col[rt]=-1;
}
}
void update(int left,int right,int c,int l,int r,int rt)
{
if(left<=l&&right>=r)
{
col[rt]=c;
return;
}
pushdown(rt);
int mid=(l+r)>>1;
if(left<=mid)
update(left,right,c,lson);
if(right>mid)
update(left,right,c,rson);
}
void query(int l,int r,int rt)
{
if(col[rt]!=-1)
{
if(!flag[col[rt]])
ans++;
flag[col[rt]]=1;
return;
}
if(l==r) return;
int mid=(l+r)>>1;
query(lson);
query(rson);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ans=0;
memset(col,-1,sizeof(col));
memset(flag,0,sizeof(flag));
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d%d",&li[i],&ri[i]);
int nn=0;
for(int i=0;i<n;i++)
{
x[nn++]=li[i];
x[nn++]=ri[i];
}
sort(x,x+nn);
m=1;
for(int i=1;i<nn;i++)
{
if(x[i]!=x[i-1])
x[m++]=x[i];
}
for(int i=m-1;i>=0;i--)
{
if(x[i]!=(x[i-1]+1))
x[m++]=x[i-1]+1;
}
sort(x,x+m);
for(int i=0;i<n;++i)
{
int l=Bsearch(li[i]);
int r=Bsearch(ri[i]);
update(l,r,i,0,m-1,1);
}
query(0,m-1,1);
printf("%d\n",ans);
}
return 0;
}