题意:在墙上贴海报,海报之间可以互相覆盖,问最后可以看见几张海报.
思路:这题数据范围很大,直接搞容易超时+超内存,需要离散化.
离散化简单来说就是只取我们需要用到的值来用,比如说区间[1000,2000],[1990,2012]
我们用不到[-inf,999][1001,1989],[1991,1999],[2001,2011][2013,+inf]这些值,
所以只需要1000,1990,2000,2012就够了,将其分别映射到0,1,2,3复杂度就会降下来.
所以离散化就是保存所有需要用到的值,排序后,分别映射到1-n,就可以降低复杂度.
但是这题每个数字其实表示一个单位长度(并非一个点),普通离散化会造成许多错误.
比如:
1-10 1-4 5-10
1-10 1-4 6-10
离散化后都是[1,4][1,2][3,4]
为了解决这种缺陷,我们可以在排序后的数组上加些处理,比如说[1,2,6,10]
如果相邻数字间距大于1的话,在其中加上任意一个数字,比如加成[1,2,3,6,7,10],然后再做线段树就好了.
线段树功能:update:成段替换 query:简单hash
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #define lson l,m,rt<<1 6 #define rson m+1,r,rt<<1|1 7 8 const int maxn = 11111; 9 bool hash[maxn]; 10 int li[maxn],ri[maxn]; 11 int x[maxn*3]; 12 int col[maxn<<4]; 13 int cnt; 14 15 void pushDown(int rt) 16 { 17 if(col[rt]!=-1) 18 { 19 col[rt<<1]=col[rt<<1|1]=col[rt]; 20 col[rt]=-1; 21 } 22 } 23 24 void update(int L,int R,int c,int l,int r,int rt) 25 { 26 if(L<=l&&r<=R) 27 { 28 col[rt]=c; 29 return; 30 } 31 pushDown(rt); 32 int m=(l+r)>>1; 33 if(L<=m) update(L,R,c,lson); 34 if(m<R) update(L,R,c,rson); 35 } 36 37 void query(int l,int r,int rt) 38 { 39 if(col[rt]!=-1) 40 { 41 if(!hash[col[rt]]) cnt++; 42 hash[col[rt]]=true; 43 return; 44 } 45 if(l==r) return; 46 int m=(l+r)>>1; 47 query(lson); 48 query(rson); 49 } 50 51 int Bin(int key,int n,int x[]) 52 { 53 int l=0,r=n-1; 54 while(l<=r) 55 { 56 int m=(l+r)>>1; 57 if(x[m]==key) return m; 58 if(x[m]<key) l=m+1; 59 else r=m-1; 60 } 61 return -1; 62 } 63 64 int main() 65 { 66 //freopen("a.txt","r",stdin); 67 int t,n; 68 scanf("%d",&t); 69 while(t--) 70 { 71 scanf("%d",&n); 72 int nn=0; 73 for(int i=0;i<n;i++) 74 { 75 scanf("%d%d",&li[i],&ri[i]); 76 x[nn++]=li[i]; 77 x[nn++]=ri[i]; 78 } 79 sort(x,x+nn); 80 int m=1; 81 for(int i=1;i<nn;i++) //去掉重复的 82 { 83 if(x[i]!=x[i-1]) x[m++]=x[i]; 84 } 85 for(int i=m-1;i>0;i--) //如果间距大于1就插入任意一个数 86 { 87 if(x[i]!=x[i-1]+1) x[m++]=x[i-1]+1; 88 } 89 sort(x,x+m); 90 memset(col,-1,sizeof(col)); 91 for(int i=0;i<n;i++) //二分查找左右边界在x中的位置 92 { 93 int l=Bin(li[i],m,x); 94 int r=Bin(ri[i],m,x); 95 update(l,r,i,0,m,1);//用第i种颜色更新 96 } 97 cnt=0; 98 memset(hash,0,sizeof(hash)); 99 query(0,m,1); 100 printf("%d ",cnt); 101 } 102 return 0; 103 }