hiho一下 第二十一周 离散化与线段树回顾

             题意:

                      有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;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值