您的位置:首页 > 其它

kb-07专题线段树-04--离散化;

2015-05-30 23:29 447 查看
/*
poj2528
  线段树 好题,用到了离散化,二分定位,特殊的区间查寻方式;在下面的代码注释中有详细的解释;
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
typedef struct
{
int l,r;
int cnt;//记录该段有几张海报;
int num;//记录该段下面是哪一张海报,0表示没有还海报或海报不唯一;
}Node;
int a[400010][2],n,dot[400010]={0},cou[400010]={0};
Node tr[800010];
void build(int rt,int l,int r)
{
tr[rt].l=l;
tr[rt].r=r;
tr[rt].cnt=0;
tr[rt].num=0;
if(l==r)
return ;
int mid=(l+r)/2;
build(rt<<1,l,mid);
build((rt<<1)|1,mid+1,r);
}
void Pushdown(int rt)
{
tr[rt<<1].cnt=1;
tr[rt<<1|1].cnt=1;
tr[rt<<1].num=tr[rt].num;
tr[rt<<1|1].num=tr[rt].num;
tr[rt].cnt=2;
tr[rt].num=0;
}
void Update(int rt,int l,int r,int x)
{
if(tr[rt].l==l&&tr[rt].r==r)
{
tr[rt].cnt=1;
tr[rt].num=x;
return;
}
if(tr[rt].cnt==1)//当只有一张海报在这个区间的时候才需要pushdown所以可以判断一下;也可以写在pushdown函数里面,我觉得写在外面比较块;
Pushdown(rt);
if(l<=tr[rt<<1].r)
{
if(r<=tr[rt<<1].r)
Update(rt<<1,l,r,x);
else
Update(rt<<1,l,tr[rt<<1].r,x);
}
if(r>=tr[rt<<1|1].l)
{
if(l>=tr[rt<<1|1].l)
Update(rt<<1|1,l,r,x);
else
Update(rt<<1|1,tr[rt<<1|1].l,r,x);
}
if(tr[rt<<1].num==tr[rt<<1|1].num&&tr[rt<<1].cnt==1&&tr[rt<<1|1].cnt==1)//这以下是pushup的操作,写在这里了;
{
tr[rt].cnt=1;
tr[rt].num=tr[rt<<1].num;
}
else
tr[rt].cnt=2;
}
/*
查询操作比较有趣,因为是查寻区间的海报种类,一个海报可能是首尾可见而中间不可见,所以没办法直接查得,
所以在树的结点上记录的是海报的编号,这样就可以用一个辅助的数组记录哪一个在此次查询中出现过;、
所以每次查询要全区间查询,然后再扫一遍数组;
、每次扫到区间内容一质的时候就不用再扫了;
*/
void Query(int rt)
{
if(tr[rt].cnt==1)
{
cou[tr[rt].num]=1;
return ;
}
if(tr[rt].l==tr[rt].r)
return ;
if(tr[rt].cnt==0)
return ;
Query(rt<<1);
Query(rt<<1|1);
}
int Erfen(int l,int r,int x)//用来确定该点在线段上的位置(离散后的位置);
{
while(l<=r)
{
int mid=(l+r)/2;
if(x<dot[mid])
r=mid-1;
else
l=mid+1;
}
return r;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(dot,0,sizeof(dot));
scanf("%d",&n);
int z=0;
for(int i=0;i<n;i++)
{
scanf("%d%d",&a[i][0],&a[i][1]);
dot[z++]=a[i][0];
dot[z++]=a[i][1];
}
sort(dot,dot+z);//将输入的数据排序后是离散化;因为数据范围比较大,因为只和区间有关,与区间内部的点没有关系,所以只要区间首尾就好;
int t=1;
for(int i=1;i<z;i++)
{
if(dot[i]!=dot[i-1])
dot[t++]=dot[i];
}
for(int i=t-1;i>0;i--)
{
if(dot[i]-dot[i-1]>1)
dot[t++]=dot[i-1]+1;
}
sort(dot,dot+t);
for(int i=t;i>0;i--)
dot[i]=dot[i-1];
memset(tr,0,sizeof(tr));
build(1,1,t+5);
for(int i=1;i<=n;i++)
{
int temp1=Erfen(1,t,a[i-1][0]);
int temp2=Erfen(1,t,a[i-1][1]);
Update(1,temp1,temp2,i);
}
memset(cou,0,sizeof(cou));
Query(1);
int ans=0;
for(int i=1;i<=n;i++)
if(cou[i]==1)
ans++;
printf("%d\n",ans);
}
return 0;
151  }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: