nyoj 9 poj 2528 posters
来源:互联网 发布:59pic美女图片源码 编辑:程序博客网 时间:2024/05/21 11:25
线段树的离散化,因为贴海报的范围是1~1e7,肯定开不了那么大的数组,但是n的范围很小只有1e4,所以可以离散化处理,什么叫做离散化?
百度百科:离散化,把无限空间中无限的个体映射到有限的空间中去,以此提高算法的时空效率。
比如一组数据:
3
10000 100000
10000 20000
20000 100000
心算就能算出来应该是3,我们可以把10000假设成1,100000假设成10,20000假设成2,这样就成了
3
1 10
1 2
2 10
其实还可以继续缩小 因为10000最小排在第一,20000第二,100000第三,所以假设10000为1,20000为2,100000为3
即:
3
1 3
1 2
2 3
因此离散化就避免了很大的空间浪费,所以虽然说数的范围是1~1e7,但是只有2e4个数,我们通过映射,可以将这些数映射成1~20000的范围,这样就只需要开2w的数组即可,而不再需要开1e7的数组,是不是很神奇啊?哈哈~
不过应该怎么映射?
可以通过map映射,不过可能会超时,我们可以将所有的数sort一下,再去重,然后每个数都对应了一个次序,按照这个次序来建树,更新,最后再求范围就可以了,
poj:
http://poj.org/problem?id=2528
poj AC代码(nyoj wa):
#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>using namespace std;int num[20010],k,c[20010];struct node{ int left,right,value,mid;} w[80020];struct stu{ int x,y;} a[10010];void build(int l,int r,int tr){ w[tr].value=-1; w[tr].left=l,w[tr].right=r; if(l==r) return ; int mid=(l+r)/2; w[tr].mid=mid; build(l,mid,tr*2); build(mid+1,r,tr*2+1);}int Search(int x){ int l=1,r=k,j; while(l<=r) { j=(l+r)/2; if(num[j]==x) return j; if(x<num[j]) r=j-1; else l=j+1; }}void update(int l,int r,int zhi,int tr){ if(l==w[tr].left&&r==w[tr].right) { w[tr].value=zhi; return ; } if(w[tr].value!=-1) w[tr*2].value=w[tr*2+1].value=w[tr].value,w[tr].value=-1; if(r<=w[tr].mid) update(l,r,zhi,tr*2); else if(l>w[tr].mid) update(l,r,zhi,tr*2+1); else update(l,w[tr].mid,zhi,tr*2),update(w[tr].mid+1,r,zhi,tr*2+1);}void searchtree(int tr){ if(w[tr].value!=-1) {c[w[tr].value]++;return;} if(w[tr].left==w[tr].right) {return;} searchtree(tr*2),searchtree(tr*2+1);}int main(){ int nn; scanf("%d",&nn); while(nn--) { memset(c,0,sizeof(c)); int n,i; k=0; scanf("%d",&n); for(i=1; i<=n; i++) scanf("%d%d",&a[i].x,&a[i].y),num[++k]=a[i].x,num[++k]=a[i].y; sort(num+1,num+k+1); k=unique(num+1,num+k+1)-num-1; build(1,k,1); for(i=1; i<=n; i++) { int x=Search(a[i].x); int y=Search(a[i].y); update(x,y,i,1); } searchtree(1); int s=0; for(i=1; i<=n; i++) if(c[i]) s++; printf("%d\n",s); }}
然后换个oj提交
http://acm.nyist.net/JudgeOnline/problemset.php
这是会惊奇的发现wa了,为什么?
再来测一组数据
3
1 10
1 4
6 10
实际结果应该为3,但是代码的结果为2,为什么?
因为映射过程中成了:
3
1 4
1 2
3 4
不难理解为什么代码结果和实际为什么不一样,但是poj后台数据水,就a了,,幸亏我nyoj后台叼~,哈哈,,
改进代码:
#include<stdio.h>#include<string.h>#include<algorithm>#include<set> //set用来记录海报个数#include<iostream>using namespace std;set<int>s; //set容器int num[20010],k;struct node{ int left,right,value,mid;} w[40020];struct stu{ int x,y;} a[10010];void build(int l,int r,int tr) //建树,但是不是一般的建树法{ w[tr].value=-1; w[tr].left=l,w[tr].right=r; int mid=(l+r)/2; w[tr].mid=mid; if(l+1<r) //注意此处的建树法 { build(l,mid,tr*2); build(mid,r,tr*2+1); }}int Search(int x) //二分查找用来查找这个数对应的是离散化的哪个数字,{ int l=1,r=k,j; while(l<=r) { j=(l+r)/2; if(num[j]==x) return j; if(x<num[j]) r=j-1; else l=j+1; }}void update(int l,int r,int zhi,int tr) //区间更新{ if(l==w[tr].left&&r==w[tr].right) //若查找到此区间,则“贴上海报” { w[tr].value=zhi; return ; } if(w[tr].value!=-1) //若此区间没有找到,且此处有海报,就将其分成小块, w[tr*2].value=w[tr*2+1].value=w[tr].value,w[tr].value=-1; if(r<=w[tr].mid) update(l,r,zhi,tr*2); else if(l>=w[tr].mid) update(l,r,zhi,tr*2+1); else update(l,w[tr*2].right,zhi,tr*2),update(w[tr*2+1].left,r,zhi,tr*2+1);}void searchtree(int tr) //查询{ if(w[tr].value!=-1) s.insert(w[tr].value); //找到海报就放进set容器中,同时这个区间的子区间就不再统计, else if(w[tr].right>w[tr].left+1) { searchtree(2*tr); searchtree(2*tr+1); }}int main(){ int nn; scanf("%d",&nn); while(nn--) { int n,i; k=0; scanf("%d",&n); for(i=1; i<=n; i++) scanf("%d%d",&a[i].x,&a[i].y),a[i].x--,num[++k]=a[i].x,num[++k]=a[i].y; //num数组用来排序,便于离散化,至于为什么要a[i]--,自己想想,哈哈~ sort(num+1,num+k+1); //num排序, k=unique(num+1,num+k+1)-num-1; //用了unique函数,目的是去除排序后的重复数字, build(1,k,1); //建树 for(i=1; i<=n; i++) //n次更新 { int x=Search(a[i].x); int y=Search(a[i].y); update(x,y,i,1); } searchtree(1); //查询有多少个海报 printf("%d\n",s.size()); //输出海报个数 s.clear(); //清空set容器 } return 0;}
- nyoj 9 poj 2528 posters
- POJ 2528 Mayor's posters
- poj 2528 Mayor's posters
- POJ 2528 Mayor's Posters
- Mayor's posters poj 2528
- poj 2528 Mayor's posters
- Poj 2528 Mayor's posters
- poj 2528 Mayor's posters
- POJ 2528 Mayor's posters
- POJ 2528 Mayor's posters
- POJ 2528 - Mayor's posters
- POJ-2528-Mayor's posters
- poj 2528 Mayor's posters
- poj 2528 Mayor's posters
- poj 2528 Mayor's posters
- POJ 2528 Mayor's posters
- POJ 2528 Mayor's posters
- Poj 2528 Mayor's posters
- GameCenter
- Lucene学习总结之二:Lucene的总体架构
- android IPC通信机制梳理
- iOS开发UI之初识CALayer
- HTTP请求的TCP瓶颈分析
- nyoj 9 poj 2528 posters
- php 利用Access-Control-Allow-Origin响应头解决跨域请求
- eclipse启动弹出Subversion Native Library Not Available
- 迅雷之CDN加速下载/离线下载
- 如何处理服务器SSL收到了一个弱临时Diffie-Hellman 密钥?
- 内购
- 当AR遇到智能家居 看看微软HoloLens如何控制台灯?
- iCloud
- 录制视频之MediaRecorder