http://poj.org/problem?id=2528
题目大意是市长竞选要贴海报,给出墙的长度和依次张贴的海报的长度区间(参考题目给的图),问最后你能看见的海报有几张
就是有的先贴的海报可能会被后贴的海报完全盖住,那就看不见了
这里就非常抽象的区间更新,墙的长度为建立线段树的总区间,每贴一张海报代表将这个区间的颜色涂为相应的,每张海报的颜色当然
都不相同,求最后又多少种颜色就行,但这里还要用到基础的离散化
离散化是把无限空间中无限的个体映射到有限的空间中去,以此提高算法的时空效率。
简单点说,假设区间长度有一亿甚至跟多,但是区间里具体的值却最多只用到了一百万,且不说能否开那么大的数组,也造成了
内存的浪费,所以用离散化来节省不必要的浪费
举这个题目的样例来说(前三个)
如果只是改变区间1 7 2 6 8 10的颜色,那么剩下的数字并没有用到
那么我们将这些数字排序,x[1]=1 x[2]=2 x[3]=6 x[4]=7 x[5]=8 x[6]=10
但是如果每个相邻的差值大于1的时候要插入一个数(就插入x[i]-1好了),
(如果不插的话
假设三张海报为:1 10 1 4 6 10
离散化时 x[1] = 1 x[2]=4 X[3]=6 X[4]=10
第一张海报时:墙的1~4被染为1;
第二张海报时:墙的1~2被染为2,3~4仍为1;
第三张海报时:墙的3~4被染为3,1~2仍为2。
最终,第一张海报就显示被完全覆盖了,然后输出2,但是正确答案明显是3)
插入后新的排序为x[1]=1 x[2]=2 x[3]=5 x[4]=6 x[5]=7 x[6]=8 x[7]=9 x[8]=10
然后以这个新的长度为8的数组区间建树就好
code
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 struct point { 7 int l,r; 8 int mark,sum; 9 }; 10 point tree[10001*4*4],num[10001*4]; 11 int ans,res[10001*4],visit[10001*4]; 12 void build(int i,int left,int right) 13 { 14 tree[i].l=left,tree[i].r=right; 15 tree[i].mark=tree[i].sum=0; 16 if (left==right) return ; 17 int mid=(left+right)/2; 18 build(i*2,left,mid); 19 build(i*2+1,mid+1,right); 20 } 21 void update(int i,int left,int right,int val) 22 { 23 if (left<=tree[i].l&&tree[i].r<=right){tree[i].mark=tree[i].sum=val;return ;} 24 if (tree[i].mark) 25 { 26 tree[i*2].mark=tree[i*2+1].mark=tree[i].mark; 27 tree[i*2].sum=tree[i*2+1].sum=tree[i].mark; 28 tree[i].mark=0; 29 } 30 int mid=(tree[i].r+tree[i].l)/2; 31 if (left>mid) update(i*2+1,left,right,val); 32 else if (right<=mid) update(i*2,left,right,val); 33 else 34 { 35 update(i*2,left,mid,val); 36 update(i*2+1,mid+1,right,val); 37 } 38 } 39 int find(int i) 40 { 41 if (tree[i].l==tree[i].r) 42 { 43 if (!visit[tree[i].sum]) 44 { 45 visit[tree[i].sum]=1; 46 ++ans; 47 } 48 return ans; 49 } 50 if (tree[i].mark) 51 { 52 tree[i*2].mark=tree[i*2+1].mark=tree[i].mark; 53 tree[i*2].sum=tree[i*2+1].sum=tree[i].mark; 54 tree[i].mark=0; 55 } 56 find(i*2); 57 find(i*2+1); 58 } 59 int main() 60 { 61 int t,i,n,tn,tn1,powr,powl; 62 scanf("%d",&t); 63 64 if (t==0) return 0; 65 while (t--) 66 { 67 res[0]=0; 68 scanf("%d",&n); 69 for (i=1;i<=n;i++) 70 { 71 scanf("%d %d",&num[i].l,&num[i].r); 72 if (num[i].l>num[i].r) swap(num[i].l,num[i].r); 73 res[++res[0]]=num[i].l; 74 res[++res[0]]=num[i].r; 75 } 76 sort(res+1,res+res[0]+1);//离散化 77 tn1=tn=unique(res+1,res+res[0]+1)-res; 78 for (i=2;i<tn;i++)//插入数 79 if (res[i]-res[i-1]>1) 80 res[tn1++]=res[i]-1; 81 res[0]=tn1-1; 82 sort(res+1,res+res[0]+1); 83 build(1,1,res[0]);//以新的区间建树 84 for (i=1;i<=n;i++) 85 { 86 powl=lower_bound(res+1,res+1+res[0],num[i].l)-res; 87 powr=lower_bound(res+1,res+1+res[0],num[i].r)-res; 88 update(1,powl,powr,i); 89 } 90 ans=0; 91 memset(visit,0,sizeof(visit)); 92 visit[0]=1; 93 printf("%d\n",find(1)); 94 } 95 96 return 0; 97 }