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;
} 

 

posted @ 2016-06-01 17:22  FireCool  阅读(290)  评论(0编辑  收藏  举报