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 }
相关文章推荐
- 安卓UI线程与异步消息处理机制
- 在pythonanywhere上搭建django程序(Virtualenv+python2.7+django1.7+)
- 第一节:定义异常
- Android Studio 中如何更改SDK路径
- uibutton(上下左右箭头加放大和缩小) 封装
- 简单数据库sql语言
- 制定测试计划~201303014010 张萍萍
- CSS中a:hover在浏览器中无法显示
- 如何使用回调函数
- JAVA中创建JSON数据
- lwwtcode 13-Roman to interge
- python学习笔记之――函数模块
- 第五十八天 how can I 坚持
- 2015.5.30
- 【python】数据库操作
- 百度2014校园招聘笔试题 ——深度学习算法研发工程师.
- ORA-01034和ORA-27101的错误
- 百度2014校园招聘笔试题 ——深度学习算法研发工程师.
- Spring+SpringMVC+Mybatis+Mysql整合实例
- css3 text-overflow和word-wrap