pku2528(线段树加离散化)
2011-05-01 13:15
288 查看
悲剧呀,这道题目搞了那么久,原来是离散化的方法出现问题了,悲剧,实在悲剧
线段树 + 离散化
今天做了这道题目的时候, 也算是明白了 离散化 的基本
意思,因为 题目的 数据范围很大 , 1- 10000000,直接线段树的话, 先不说
内存会不会爆, 这么大的范围估计也是 TLE了.
仔细读题, 可以看到 1<= N <= 10000, 也就是说 最多只有 10000个点, 如果
每个点都不同, 那么最多也只有 20000 个数据, 那么离散后的 范围就相当小;
离散化 的大概思路 : 比如说给你一组 数据 1 4 1000 100000, 如果直接
开线段, 显然是浪费, 那么我们只要 进行 映射 :
1 1
4 2
1000 3
100000 4
接下来 我们只要对 1 2 3 4 建立线段树就行了 只需要
[1,4]的区间
嘿嘿,这个是刚写的代码,简洁了许多,也快了一点
线段树 + 离散化
今天做了这道题目的时候, 也算是明白了 离散化 的基本
意思,因为 题目的 数据范围很大 , 1- 10000000,直接线段树的话, 先不说
内存会不会爆, 这么大的范围估计也是 TLE了.
仔细读题, 可以看到 1<= N <= 10000, 也就是说 最多只有 10000个点, 如果
每个点都不同, 那么最多也只有 20000 个数据, 那么离散后的 范围就相当小;
离散化 的大概思路 : 比如说给你一组 数据 1 4 1000 100000, 如果直接
开线段, 显然是浪费, 那么我们只要 进行 映射 :
1 1
4 2
1000 3
100000 4
接下来 我们只要对 1 2 3 4 建立线段树就行了 只需要
[1,4]的区间
嘿嘿,这个是刚写的代码,简洁了许多,也快了一点
#include<iostream> #include<map> #include<set> #define MAXN 10010 using namespace std; struct node { int c; }p[MAXN*8]; int left1[MAXN],right1[MAXN],n,m,num; bool col[MAXN]; map<int,int> map1; map<int,int>::iterator it; void bulid(int k,int s,int t) { if(t==s) return ; p[k].c=0; int kl=k<<1,kr=kl+1,mid=(s+t)>>1; bulid(kl,s,mid); bulid(kr,mid+1,t); } void insert(int k,int s,int t,int l,int r,int e) { if(l>t||r<s) return ; if(l<=s&&t<=r) { p[k].c=e; return ; } int kl=k<<1,kr=kl+1,mid=(s+t)>>1; if(p[k].c!=-1) { p[kl].c=p[kr].c=p[k].c; p[k].c=-1; } insert(kl,s,mid,l,r,e); insert(kr,mid+1,t,l,r,e); } void query(int k,int s,int t) { if(p[k].c!=-1) { if(!col[p[k].c]) { num++; col[p[k].c]=true; } return ; } int kl=k<<1,kr=kl+1,mid=(s+t)>>1; query(kl,s,mid); query(kr,mid+1,t); } int main() { int cas; scanf("%d",&cas); while(cas--) { map1.clear(); scanf("%d",&m); for(int i=0;i<m;i++) { scanf("%d %d",&left1[i],&right1[i]); map1[left1[i]]=10; map1[right1[i]]=10; } it=map1.begin(); int i=1; for(;it!=map1.end();i++,it++) it->second=i; n =i; bulid(1,1,n); for(int i=0;i<m;i++) insert(1,1,n,map1[left1[i]],map1[right1[i]],i+1); num=0; memset(col,false,sizeof(col)); col[0]=true; query(1,1,n); printf("%d\n",num); } return 0; }
#include<set> #include<map> #include<stdio.h> #include<stdlib.h> #include<string.h> using namespace std; #define MAX_N 20010 struct In { int left; int right; }str[MAX_N]; struct Node { int l; int r; int col; }p[8*MAX_N]; set<int> my_set; map<int,int> mp; map<int,int>::iterator beg,end1; int cmp( const void *a , const void *b ){ return *(int *)a-*(int *)b; } void bulid(int k,int s,int t) { int kr,kl,mid; p[k].l=s;p[k].r=t;p[k].col=0; if(s==t) return ; mid=(s+t)>>1;kl=k<<1;kr=kl+1; bulid(kl,s,mid); bulid(kr,mid+1,t); } void insert(int k,int s,int t,int v) { int kr,kl,mid; if(s==p[k].l&&t==p[k].r) { p[k].col=v; } else { mid=(p[k].l+p[k].r)>>1;kl=k<<1;kr=kl+1; if(p[k].col!=-1) { p[kl].col=p[kr].col=p[k].col; p[k].col=-1; } if(t<=mid) insert(kl,s,t,v); else if(s>mid) insert(kr,s,t,v); else { insert(kl,s,mid,v); insert(kr,mid+1,t,v); } } } void query(int k,int s,int t) { if(p[k].col!=-1) { my_set.insert(p[k].col);//将颜色插入set中,自动去重 return ; } int mid=(p[k].r+p[k].l)>>1,kl=k<<1,kr=kl+1; if(t<=mid) query(kl,s,t) ; else if(s>mid) query(kr,s,t); else { query(kl,s,mid);query(kr,mid+1,t); } } int main() { int i,j,cas,n,m,num; scanf("%d",&cas); bulid(1,1,MAX_N); while(cas--) { my_set.clear(); mp.clear(); scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d %d",&str[i].left,&str[i].right); mp[str[i].left] = 10; mp[str[i].right] = 10; } beg = mp.begin(), end1 = mp.end(); insert(1,1,2*n,0); //因为map 已经自动排序了,所以直接从 1 --> N 开始标记, 离散化 for ( int i = 1;beg != end1; ++ beg, ++ i ) { beg->second = i; } //因为线段树已经建立好了, 所以没必要每次都重建一次, 只要插入一条 //覆盖所有区间的 底板 就行了 for ( int i = 1; i <= n; ++ i ) { //用离散后的标记 插入 线段 insert ( 1,mp[str[i].left], mp[str[i].right], i ); } query(1,1,2*n); num=my_set.size();//返回集合中元素个数 if(*my_set.begin()==0) num--; printf("%d\n",num); } return 0; }
相关文章推荐
- pku2528 线段树(离散化)
- Codeforces Gym 100733J Summer Wars 线段树,区间更新,区间求最大值,离散化,区间求并
- HDU 4325 线段树离散化
- POJ2528解题报告,区间离散化,线段树
- Mayor's posters(线段树+离散化POJ2528)
- poj 2528 Mayor's posters (线段树+离散化+hash)
- poj2299--B - Ultra-QuickSort(线段树,离散化)
- hdoj 1542 && poj 1151 Atlantis && poj 1389 Area of Simple Polygons 【线段树 + 离散化 + 扫描线】
- hdu 4288 线段树 (离散化的离线算法)
- poj 1177 Picture (线段树 扫描线 离散化 矩形周长并)
- 【BNU Summer Training 2014.08.11】 Nested Segments (线段树,离散化)
- POJ 3277 City Horizon(线段树+扫描线+离散化)
- POJ 2528(线段树,区间覆盖,离散化思想)
- HDU-1255 覆盖的面积(线段树扫描线+离散化+改进后超快的算法)
- HDOJ 4325 Flowers 【线段树 离散化 区间更新 单点查询】
- HPU 1721: 感恩节KK专场——雪人的高度【线段树 离散化】
- hdu4288 Coder(线段树+离散化)
- 【HDU1199】 离散化线段树
- hdu 线段树 (矩形面积并+离散化+二分查找)
- CodeForces 19D Points(离散化+线段树+单点更新)