http://acm.hdu.edu.cn/showproblem.php?pid=4325;
题目意思:
给你N个花开的时间段,然后在有M个时间点,问你在这个时间点有多少花开着。
昨天刚做的一个类似的题,用线段树加离散化,然后赶紧敲,然后错八次。
最后还是没做出来。
那么思路还是线段树加离散化。
题目给的每个花开花谢的范围很大,但花的数目只有1e5,很容易就想到了离散化,然后就是用线段树去处理,找每个花开的段,最后lazy下放到
每个时间点,这样就知道每个时间点开的花数。
这题大致思路是这样的,但你会发现M次查询时,有的时间点,你在离散化时,你没将它加入,所以你在离散化后的数组里找不到这个点。当时没想到将询问的点加入一起离散化,然后各种二分,然并ruan.。
下面给出代码:
1 /*sjy*/ 2 #include<stdio.h> 3 #include<algorithm> 4 #include<stdlib.h> 5 #include<string.h> 6 #include<iostream> 7 #include<math.h> 8 void add(int l,int r,int k,int aa,int dd); 9 int kr(int n,int m,int t); 10 void lazy(int l,int r,int k); 11 int findd(int l,int r,int k,int aa,int dd); 12 int cmp(const void*p,const void*q); 13 /*int er(int n,int m,int t);*/ 14 typedef struct pp 15 { 16 int x; 17 int y; 18 }ss; 19 int N,M,V; 20 int tree[8*100005];//线段树数组 21 ss a[100005]; 22 ss b[2*100005]; 23 int c[2*100005]; 24 /*int yk[2*100005];*/ 25 int kp[100005]; 26 using namespace std; 27 int main(void) 28 { 29 int n,i,j,k,p,q,x,y,s; 30 scanf("%d",&n); 31 for(i=1; i<=n; i++) 32 { 33 memset(tree,0,sizeof(tree)); 34 scanf("%d %d",&N,&M); 35 int cnt=0; 36 int sum=-1; 37 for(j=0; j<N; j++) 38 { 39 scanf("%d %d",&a[j].x,&a[j].y); 40 b[cnt].x=a[j].x; 41 cnt++; 42 b[cnt].x=a[j].y; 43 cnt++; 44 if(sum<a[j].y) 45 { 46 sum=a[j].y; 47 } 48 } 49 for(j=0;j<M;j++) 50 { 51 scanf("%d",&kp[j]); 52 b[cnt++].x=kp[j]; 53 }//询问的点加入离散化 54 qsort(b,cnt,sizeof(ss),cmp);//排序离散化 55 int vv=0; 56 c[vv]=0; 57 int rr=0; 58 for(j=1; j<cnt; j++) 59 { 60 if(b[j].x!=b[j-1].x) 61 { 62 vv++; 63 c[j]=vv; 64 rr=0; 65 /*yk[j]=rr;*/ 66 } 67 else 68 { 69 c[j]=vv; 70 /*yk[j]=rr;*/ 71 } 72 } 73 for(j=0; j<N; j++) 74 { 75 x=kr(0,cnt-1,a[j].x);//二分找点 76 y=kr(0,cnt-1,a[j].y); 77 add(x,y,0,0,vv);//线段数更新加段 78 } 79 lazy(0,vv,0);printf("Case #%d: ",i); 80 for(j=0;j<M;j++) 81 { 82 int uu=kr(0,cnt-1,kp[j]); 83 int yy=findd(uu,uu,0,0,vv);//查询问的时间段因为为点所以l=r 84 printf("%d ",yy); 85 } 86 87 } 88 return 0; 89 90 } 91 void add(int l,int r,int k,int aa,int dd)//线段数更新 92 { 93 if(l>dd||r<aa) 94 { 95 return ; 96 } 97 else if(l<=aa&&r>=dd) 98 { 99 tree[k]++; 100 } 101 else 102 { 103 add(l,r,2*k+1,aa,(aa+dd)/2); 104 add(l,r,2*k+2,(aa+dd)/2+1,dd); 105 } 106 } 107 108 void lazy(int l,int r,int k)//最后下放操作 109 { 110 if(l==r) 111 { 112 return ; 113 } 114 else 115 { 116 tree[2*k+1]+=tree[k]; 117 tree[2*k+2]+=tree[k]; 118 lazy(l,(l+r)/2,2*k+1); 119 lazy((l+r)/2+1,r,2*k+2); 120 } 121 } 122 123 124 int findd(int l,int r,int k,int aa,int dd) 125 { 126 if(l>dd||r<aa) 127 { 128 return 0; 129 } 130 else if(l<=aa&&r>=dd) 131 { 132 return tree[k]; 133 } 134 else 135 { 136 int nx=findd(l,r,2*k+1,aa,(aa+dd)/2); 137 int ny=findd(l,r,2*k+2,(aa+dd)/2+1,dd); 138 return nx+ny; 139 } 140 141 } 142 143 /*int er(int n,int m,int t) 144 { 145 int y=(n+m)/2; 146 if(b[y].x==t) 147 { 148 return c[y]; 149 } 150 if(m<n) 151 { 152 return -1; 153 } 154 if(m==n&&b[m].x!=t) 155 { 156 return -1; 157 } 158 159 else if(m-n==1&&b[n].x<=t&&b[m].x>=t) 160 { 161 V=yk[n]; 162 return c[n]; 163 } 164 else if(b[y].x<t) 165 { 166 return er(y,m,t); 167 } 168 else return er(n,y,t); 169 170 }*/ 171 int kr(int n,int m,int t)//二分找点 172 { 173 int yy=(n+m)/2; 174 if(b[yy].x==t) 175 { 176 return c[yy]; 177 } 178 else if(b[yy].x>t) 179 { 180 return kr(n,yy-1,t); 181 } 182 else return kr(yy+1,m,t); 183 } 184 int cmp(const void*p,const void*q) 185 { 186 ss*w=(ss*)p; 187 ss*ww=(ss*)q; 188 189 return w->x-ww->x; 190 }