您的位置:首页 > 其它

hihoCoder:#1079(线段树+离散化)

2016-05-09 17:11 344 查看
题目大意:给n个区间,有的区间可能覆盖掉其他区间,问没有完全被其他区间覆盖的区间有几个?区间依次给出,如果有两个区间完全一样,则视为后面的覆盖前面的。

题目分析:区间可能很长,所以要将其离散化。但离散化之后区间就变成了连续的,不再是离散的。也就是叶子由左右端点为u、u变成了左右端点为u-1、u,左右儿子有(l,mid)和(mid+1,r)变成了(l,mid)和(mid,r)。所以离散化之后要以长度为1的区间为叶子节点建立线段树,而不是以1、2、3...为叶子节点建线段树。

代码如下:

# include<iostream>
# include<cstdio>
# include<set>
# include<map>
# include<cstring>
# include<algorithm>
using namespace std;

const int N=200000;

int tr[N*4+5];
int n,m;
int lazy[N*4+5];
int x[N+5],y[N+5];
set<int>s;
map<int,int>mp;
int num[N+5];

void pushDown(int rt,int l,int r)
{
if(lazy[rt]==-1) return ;
lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
tr[rt<<1]=tr[rt<<1|1]=tr[rt];
lazy[rt]=-1;
}

void update(int rt,int l,int r,int L,int R,int val)
{
if(L<=l&&r<=R){
tr[rt]=val;
lazy[rt]=val;
}else{
pushDown(rt,l,r);
int mid=l+(r-l)/2;
if(L<=mid) update(rt<<1,l,mid,L,R,val);
if(R>mid) update(rt<<1|1,mid+1,r,L,R,val);
}
}

void query(int rt,int l,int r)
{
if(l==r){
if(tr[rt]!=-1) s.insert(tr[rt]);
return ;
}
if(lazy[rt]!=-1){
s.insert(tr[rt]);
return ;
}
int mid=l+(r-l)/2;
query(rt<<1,l,mid);
query(rt<<1|1,mid+1,r);
}

int f(int l,int r,int x)
{
while(l<r){
int mid=l+(r-l)/2;
if(num[mid]<x)
l=mid+1;
else
r=mid;
}
return l;
}

int main()
{
while(~scanf("%d%d",&n,&m))
{
num[0]=0;
mp.clear();
for(int i=0;i<n;++i){
scanf("%d%d",x+i,y+i);
if(mp[x[i]]==0) num[++num[0]]=x[i],++mp[x[i]];
if(mp[y[i]]==0) num[++num[0]]=y[i],++mp[y[i]];
}
sort(num+1,num+num[0]+1);
memset(tr,-1,sizeof(tr));
memset(lazy,-1,sizeof(lazy));
for(int i=0;i<n;++i){
int a=f(1,num[0]+1,x[i]);
int b=f(1,num[0]+1,y[i]);
update(1,1,num[0]-1,a,b-1,i);
}
s.clear();
query(1,1,num[0]-1);
printf("%d\n",s.size());
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: