一个线段树关于区间更新的题目。贴海报最后求能够看见的海报的数目,按照贴的顺序依次对线段树的[l,r]区间进行更新,注意使用延迟标记。由于数据较大,所以必须先离散化处理,即取海报的区间的两端的值存储下来,然后排序映射到1,2,3,......n然后对每张海报按照区间端点对应的映射号更新即可。
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #define N 11111 5 #define M 11111111 6 #define lson l,m,rt<<1 7 #define rson m+1,r,rt<<1|1 8 9 int color[N<<4]; 10 int tag[N],flag[M],imag[N*3],ans; 11 12 void PushDown(int rt) 13 { 14 if(color[rt]) 15 { 16 color[rt<<1]=color[rt<<1|1]=color[rt]; 17 color[rt]=0; 18 } 19 } 20 21 void update(int L,int R,int c,int l,int r,int rt) 22 { 23 if(L<=l&&R>=r) 24 { 25 color[rt]=c; 26 return; 27 } 28 int m=(l+r)>>1; 29 PushDown(rt); 30 if(L<=m) 31 update(L,R,c,lson); 32 if(R>m) 33 update(L,R,c,rson); 34 } 35 36 void query(int l,int r,int rt) 37 { 38 if(color[rt]) 39 { 40 if(!tag[color[rt]]) 41 { 42 ans++,tag[color[rt]]=1; 43 } 44 return; 45 } 46 int m=(l+r)>>1; 47 if(l==r) 48 return; 49 query(lson); 50 query(rson); 51 52 } 53 54 int x[N],y[N]; 55 int cmp(const void*_a,const void*_b) 56 { 57 int *a=(int*)_a; 58 int *b=(int*)_b; 59 return (*a)-(*b); 60 } 61 int search(int n,int x) 62 { 63 int l=1,r=n; 64 while(1) 65 { 66 int m=(l+r)>>1; 67 if(flag[m]==x) 68 return m; 69 if(flag[m]<x) 70 l=m+1; 71 else r=m-1; 72 } 73 return -1; 74 } 75 76 int main(void) 77 { 78 int cs,n,i; 79 scanf("%d",&cs); 80 while(cs--) 81 { 82 memset(color,0,sizeof(color)); 83 memset(flag,0,sizeof(flag)); 84 memset(tag,0,sizeof(tag)); 85 86 int ct=0,st=0; 87 ans=0; 88 scanf("%d",&n); 89 for(i=1;i<=n;i++) 90 { 91 scanf("%d%d",x+i,y+i); 92 if(!flag[x[i]]) 93 imag[ct++]=x[i],flag[x[i]]=1; 94 if(!flag[y[i]]) 95 imag[ct++]=y[i],flag[y[i]]=1; 96 } 97 qsort(imag,ct,sizeof(int),cmp); 98 for(i=0;i<ct;i++) 99 { 100 flag[++st]=imag[i]; 101 if(i!=ct-1) 102 { 103 if(imag[i+1]-imag[i]>1) 104 flag[++st]=imag[i]+1; 105 } 106 } 107 for(i=1;i<=n;i++) 108 { 109 int l=search(st,x[i]); 110 int r=search(st,y[i]); 111 update(l,r,i,1,st,1); 112 } 113 query(1,st,1); 114 printf("%d ",ans); 115 } 116 return 0; 117 }