对应POJ题目:点击打开链接
Time Limit: 1000MS | Memory Limit: 65536KB | 64bit IO Format: %I64d & %I64u |
Description
Input
Output
Sample Input
1 5 1 4 2 6 8 10 3 4 7 10
Sample Output
4
Source
题意:就是不断地放某一区间长度的线段,后放的会把前放的覆盖,问最后有多少条线段是可见的(没被完全覆盖的都是可见的)
思路:直接用数组别想了~可以用线段树,但是根太大,要离散化。
离散化下面说得很清楚~秒懂!
通俗点说,离散化就是压缩区间,使原有的长区间映射到新的短区间,但是区间压缩前后的覆盖关系不变。举个例子:
有一条1到10的数轴(长度为9),给定4个区间[2,4] [3,6] [8,10] [6,9],覆盖关系就是后者覆盖前者,每个区间染色依次为 1 2 3 4。
现在我们抽取这4个区间的8个端点,2 4 3 6 8 10 6 9
然后删除相同的端点,这里相同的端点为6,则剩下2 4 3 6 8 10 9
对其升序排序,得2 3 4 6 8 9 10
然后建立映射
2 3 4 6 8 9 10
↓ ↓ ↓ ↓ ↓ ↓ ↓
1 2 3 4 5 6 7
那么新的4个区间为 [1,3] [2,4] [5,7] [4,6],覆盖关系没有被改变。新数轴为1到7,即原数轴的长度从9压缩到6,显然构造[1,7]的线段树比构造[1,10]的线段树更省空间,搜索也更快,但是求解的结果却是一致的。
离散化时有一点必须要注意的,就是必须先剔除相同端点后再排序,这样可以减少参与排序元素的个数,节省时间。
离散化我用的是STL里面的map~或者是二分。。。
#include<cstdio> #include<cstdlib> #include<cmath> #include<map> #include<queue> #include<stack> #include<vector> #include<algorithm> #include<cstring> #include<string> #include<iostream> const int MAXN=10000+10; #define ms(x,y) memset(x,y,sizeof(x)) using namespace std; int color[MAXN*8]; int vis[MAXN];//vis[i]=1表示i海报已经存在 int ll[MAXN]; int rr[MAXN]; void down(int rt) { if(color[rt]) { color[rt<<1]=color[rt]; color[rt<<1|1]=color[rt]; color[rt]=0; } } void updata(int rt, int left, int right, int l, int r, int col) { if(left==l && right==r){ color[rt]=col; return; } down(rt); int mid=(left+right)>>1; if(mid>=r) updata(rt<<1, left, mid, l, r, col); else if(mid<l) updata(rt<<1|1, mid+1, right, l, r, col); else{ updata(rt<<1, left, mid, l, mid, col); updata(rt<<1|1, mid+1, right, mid+1, r, col); } } void query(int rt, int left, int right) { if(vis[color[rt]]) return; //该海报已存在 if(color[rt]){//该区间都被color[rt]海报覆盖 vis[color[rt]]=1; return; } int mid=(left+right)>>1; query(rt<<1, left, mid); query(rt<<1|1, mid+1, right); } int main() { //freopen("in.txt","r",stdin); int T; scanf("%d", &T); while(T--) { map<int ,int>ma;//用map离散化 ms(vis,0); ms(color,0); int n; int i; scanf("%d", &n); for(i=0; i<n; i++){ scanf("%d%d", &ll[i],&rr[i]); if(ma[ll[i]]==0) ma[ll[i]]=1;//判重 if(ma[rr[i]]==0) ma[rr[i]]=1; } map<int, int>::iterator it; int cnt=0; for(it=ma.begin(); it!=ma.end(); it++){//标序 it->second=++cnt; } int col=0; for(i=0; i<n; i++){ int l=ma[ll[i]];//映射 int r=ma[rr[i]]; updata(1,1,cnt,l,r,++col);//区间更新 } query(1,1,cnt); int ans=0; for(i=1; i<=MAXN; i++) if(vis[i]) ans++; printf("%d\n", ans); } return 0; }
#include<cstdio> #include<cstdlib> #include<cmath> #include<map> #include<queue> #include<stack> #include<vector> #include<algorithm> #include<cstring> #include<string> #include<iostream> const int MAXN=10000+10; #define ms(x,y) memset(x,y,sizeof(x)) using namespace std; int color[MAXN*8]; int vis[MAXN];//vis[i]=1表示i海报已经存在 int ll[MAXN]; int rr[MAXN]; int A[MAXN*8]; void down(int rt) { if(color[rt]) { color[rt<<1]=color[rt]; color[rt<<1|1]=color[rt]; color[rt]=0; } } void updata(int rt, int left, int right, int l, int r, int col) { if(left==l && right==r){ color[rt]=col; return; } down(rt); int mid=(left+right)>>1; if(mid>=r) updata(rt<<1, left, mid, l, r, col); else if(mid<l) updata(rt<<1|1, mid+1, right, l, r, col); else{ updata(rt<<1, left, mid, l, mid, col); updata(rt<<1|1, mid+1, right, mid+1, r, col); } } void query(int rt, int left, int right) { if(vis[color[rt]]) return; //该海报已存在 if(color[rt]){//该区间都被color[rt]海报覆盖 vis[color[rt]]=1; return; } int mid=(left+right)>>1; query(rt<<1, left, mid); query(rt<<1|1, mid+1, right); } int bsearch(int x, int n) { int left=1,right=n; while(left<=right) { int mid=left+((right-left)>>1); if(A[mid]==x) return mid; if(A[mid]>x) right=mid-1; else left=mid+1; } } int main() { //freopen("in.txt","r",stdin); int T; scanf("%d", &T); while(T--) { ms(vis,0); ms(color,0); int n; int i; int u=1; scanf("%d", &n); for(i=0; i<n; i++){ scanf("%d%d", &ll[i],&rr[i]); A[u++]=ll[i]; A[u++]=rr[i]; } sort(A, A+u); int cnt=1; int col=0; for(i=2; i<u; i++) if(A[i]!=A[i-1]) A[++cnt]=A[i]; for(i=0; i<n; i++){ int l=bsearch(ll[i],cnt);//映射 int r=bsearch(rr[i],cnt); updata(1,1,cnt,l,r,++col);//区间更新 } query(1,1,cnt); int ans=0; for(i=1; i<=MAXN; i++) if(vis[i]) ans++; printf("%d\n", ans); } return 0; }