lightoj-1089 - Points in Segments (II)(线段树+离散化)
1089 - Points in Segments (II)
PDF (English) Statistics Forum
Time Limit: 2 second(s) Memory Limit: 64 MB
Given n segments (1 dimensional) and q points, for each point you have to find the number of segments which contain that point. A point pi will lie in a segment A B if A ≤ pi ≤ B.
For example, if the segments are (6 12), (8 8), (10 12), (8 11), (0 12) and the point is 11, then it is contained by 4 segments.
Input
Input starts with an integer T (≤ 5), denoting the number of test cases.
Each case starts with a line containing two integers n (1 ≤ n ≤ 50000) and q (1 ≤ q ≤ 50000).
Each of the next n lines contains two integers Ak Bk (0 ≤ Ak ≤ Bk ≤ 108) denoting a segment.
Each of the next q lines contains an integer denoting a point. Each of them range in [0, 108].
Output
For each case, print the case number in a single line. Then for each point, print the number of segments that contain that point.
Sample Input
Output for Sample Input
1
5 4
6 12
8 8
10 12
8 11
0 12
11
12
2
20
Case 1:
4
3
1
0
写这道题之前完全不知道离散化是什么,看了几个博客,其实离散化就是用一个数组arr[N]将点存起来(映射关系),建树以N的范围建。
查询的时候用bs找到value 在arr[]的下表就可以了。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; const int MAX = 222222; int T,n,q,cnt,N; struct node{ int a,b; node(){} node(int a,int b):a(a),b(b){} }Node[MAX]; int ans[MAX],arr[MAX],cover[MAX<<2];// 注意线段树的空间复杂度最坏是O(4*N);这道题的实际测试的n大于50000,稍微开大点,开小了 result是WA 不是RE,着实坑 void pushCover(int rt){ //cout<<(rt<<1)<<endl; if(cover[rt]){ cover[rt<<1] += cover[rt]; cover[rt<<1|1] += cover[rt]; cover[rt] = 0; } return ; } void build(int l,int r,int rt){ cover[rt] = 0; if(l==r){ return ; } int mid = (l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); return ; } void update(int l,int r,int L,int R,int rt){ if(l<=L&&r>=R){ cover[rt]++; return ; } pushCover(rt); int mid = (L+R)>>1; if(l<=mid) update(l,r,L,mid,rt<<1); if(r>mid) update(l,r,mid+1,R,rt<<1|1); return ; } int query(int pos,int l,int r,int rt){ if(l==r) return cover[rt]; pushCover(rt); int mid = (l+r)>>1; if(pos<=mid) return query(pos,l,mid,rt<<1); else return query(pos,mid+1,r,rt<<1|1); return 0; } int bs(int value){ int l = 0,r = N-1; while(l<=r){ int mid = (l+r)>>1; if(arr[mid]>value) r = mid-1; else if(arr[mid]==value) return mid; else l = mid+1; } return 0; } int main(){ scanf("%d",&T); for(int t=1;t<=T;t++){ scanf("%d%d",&n,&q); cnt = 0; for(int i=0;i<n;i++){ scanf("%d%d",&Node[i].a,&Node[i].b); arr[cnt++] = Node[i].a; arr[cnt++] = Node[i].b; } for(int i=0;i<q;i++){ scanf("%d",&ans[i]); arr[cnt++] = ans[i]; } sort(arr,arr+cnt); int temp = 1; for(int i=1;i<cnt;i++) if(arr[i]!=arr[i-1]) arr[temp++] = arr[i]; N = temp; build(0,N-1,1); for(int i=0;i<n;i++) update(bs(Node[i].a),bs(Node[i].b),0,N-1,1); printf("Case %d:\n",t); for(int i=0;i<q;i++){ printf("%d\n",query(bs(ans[i]),0,N-1,1)); } } return 0; }