题意:
有n(<=10^5)个线段 ,每个线段[li,ri]的范围<=10^9。现在按顺序 将线段一个个放在线上,问最终能看到几个线段(有任何一块露出都是看到)
题解:
那么久离散10^9到10^5了...记得以前做过差不多的..这次还碰到问题了..比如:
3 10
1 4
1 1
3 4
直接离散化出1,3,4来做之后发现答案不对..因为对于第一个线段..存在[2,2]的区域是看得见的..但是离散化后不能体现出来了。所以这次做的处理是读入坐标时将其左界-1与右界+1也放到离散数列里面。
Program:
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<map>
#include<string>
#include<string.h>
#include<algorithm>
#define MAXN 400005
#define oo 1000000007
#define ll long long
using namespace std;
int P[MAXN][2],id[MAXN],T[MAXN<<2],col[MAXN<<2];
bool F[MAXN];
int find(int d,int n)
{
int l=0,r=n+1,mid;
while (r-l>1)
{
mid=l+r>>1;
if (id[mid]<=d) l=mid;
else r=mid;
}
return l;
}
void PushDown(int x)
{
if (!col[x]) return;
T[x<<1]=T[x<<1|1]=col[x];
col[x<<1]=col[x<<1|1]=col[x];
col[x]=0;
}
void Update(int l,int r,int L,int R,int d,int x)
{
if (l>=L && r<=R)
{
T[x]=col[x]=d;
return;
}
PushDown(x);
int mid=l+r>>1;
if (mid>=L) Update(l,mid,L,R,d,x<<1);
if (mid<R) Update(mid+1,r,L,R,d,x<<1|1);
}
int Query(int l,int r,int p,int x)
{
if (l==r) return T[x];
PushDown(x);
int mid=l+r>>1;
if (mid>=p) return Query(l,mid,p,x<<1);
else return Query(mid+1,r,p,x<<1|1);
}
int main()
{
int num,m,n,l,r,i,x,ans;
scanf("%d%d",&num,&m),n=0;
for (i=1;i<=num;i++)
scanf("%d%d",&P[i][0],&P[i][1]),
id[++n]=P[i][0],id[++n]=P[i][1],
id[++n]=P[i][0]-1,id[++n]=P[i][1]+1;
sort(id+1,id+1+n);
memset(T,0,sizeof(T));
memset(col,0,sizeof(col));
for (i=1;i<=num;i++)
P[i][0]=find(P[i][0],n),
P[i][1]=find(P[i][1],n);
for (i=1;i<=num;i++) Update(1,n,P[i][0],P[i][1],i,1);
memset(F,false,sizeof(F)),F[0]=true,ans=0;
for (i=1;i<=n;i++)
{
x=Query(1,n,i,1);
if (!F[x]) ans++,F[x]=true;
}
printf("%d\n",ans);
return 0;
}