LOJ 1088 Points in Segments

题目大意:

        给定n个点(1 ≤ n ≤ 10^5),每个点都有一个整数值,范围是[0, 10^8],并且已经升序排列好了(每个点的值互不相同),现在给定q个段[a, b],其中a、b∈[0, 10^8],计算序列中每个给定段中点的个数,即p∈序列,且a ≤ p ≤ b的p的个数。

       现有多个测例(测例数会给出),每个测例中都给出n和q,以及n个元素的大小(升序排列输入的)以及q个段的左端值和右端值a和b,对于每个测例的每个段都给出位于段中的元素的个数。

题目链接

C语言实现lower_bound和upper_bound:

注释代码:

/*                                      
 * Problem ID : LOJ 1088 Points in Segments  
 * Author     : Lirx.t.Una                                      
 * Language   : C++                     
 * CPU		  : 0.340                                      
 * Memory	  : 1476                                      
*/ 

#include <stdio.h>

//点集的最大长度
#define MAXN        100000
 
int     a[MAXN];
 
int
xbsrch( int lft, int rht, int x ) {//binary search in x
	//搜出大于等于x的第一个元素,即lower_bound
 
    int     mid;
 
    while ( lft < rht ) {
   
        mid = ( lft + rht ) >> 1;
 
        if ( a[mid] >= x )//一旦大于等于x就将区间置为左部
            rht = mid;//此步保证结果位置一定最左
        else//小于就mid左移
			//此步保证了结果位置的元素一定大于等于x			
            lft = mid + 1;
    }
 
    return lft;
}
 
int
ybsrch( int lft, int rht, int y ) {//binary search in y
	//搜出大于y的第一个元素,即upper_bound
 
    int     mid;
 
    while ( lft < rht ) {
   
        mid = ( lft + rht ) >> 1;
 
        if ( a[mid] > y )//一旦大于y就将区间置为右部
            rht = mid;//此步保证结果位置一定最右
        else//小于等于就mid右移
			//此步保证了结果一定大于y
            lft = mid + 1;
    }
 
    return lft;
}
 
int
main() {
 
    int     nscn, iscn;
    int     n, k;//n个点k个段
    int     x, y;//搜查的左右端点
 
    int     p1, p2;//搜查结果的左右端点的数组下标
 
    int     i;
 
    scanf("%d", &nscn);
    iscn = 0;
 
    while ( nscn-- ) {
   
        scanf("%d%d", &n, &k);
        for ( i = 0; i < n; i++ )
            scanf("%d", a + i);
 
        printf("Case %d:\n", ++iscn);
        while ( k-- ) {
       
            scanf("%d%d", &x, &y);
			
            if ( a[n - 1] < x || a[0] > y ) {
				//如果搜查区间和点序列不重合
				//则无任何元素
				
                puts("0");
                continue;
            }
			
			//特殊情况(y的srch不能正确处理这种特殊情况)
            if ( x <= a[0] )//当左搜查元素小于等于序列最左端值
                p1 = 0;//则左坐标就直接等于0(0号元素就是大于等于x的第一个元素了)
            else
                p1 = xbsrch( 0, n - 1, x );
			
            if ( y >= a[n - 1] )//对于这种情况若使用ysrch,则其返回的就是
				//序列的最后一个元素,而不是最后一个元素的后一个位置
                p2 = n;
            else
                p2 = ybsrch( p1, n - 1, y );//利用p1作为左端点,可以剪短搜索范围以节省时间
			
            printf("%d\n", p2 - p1);
        }
    }
	
    return 0;
}

无注释代码:

#include <stdio.h>
 
#define MAXN        100000
 
int     a[MAXN];
 
int
xbsrch( int lft, int rht, int x ) {
 
    int     mid;
 
    while ( lft < rht ) {
   
        mid = ( lft + rht ) >> 1;
 
        if ( a[mid] >= x )
            rht = mid;
        else
            lft = mid + 1;
    }
 
    return lft;
}
 
int
ybsrch( int lft, int rht, int y ) {
 
    int     mid;
 
    while ( lft < rht ) {
   
        mid = ( lft + rht ) >> 1;
 
        if ( a[mid] > y )
            rht = mid;
        else
            lft = mid + 1;
    }
 
    return lft;
}

int
main() {
	
    int     nscn, iscn;
    int     n, k;
    int     x, y;
	
    int     p1, p2;
	
    int     i;
	
    scanf("%d", &nscn);
    iscn = 0;
	
    while ( nscn-- ) {
		
        scanf("%d%d", &n, &k);
        for ( i = 0; i < n; i++ )
            scanf("%d", a + i);
		
        printf("Case %d:\n", ++iscn);
        while ( k-- ) {
			
            scanf("%d%d", &x, &y);
			
            if ( a[n - 1] < x || a[0] > y ) {
				
                puts("0");
                continue;
            }
			
            if ( x <= a[0] )
                p1 = 0;
            else
                p1 = xbsrch( 0, n - 1, x );
			
            if ( y >= a[n - 1] )
                p2 = n;
            else
                p2 = ybsrch( p1, n - 1, y );
			
            printf("%d\n", p2 - p1);
        }
    }
	
    return 0;
}

使用lower_bound和upper_bound二分搜索模板函数:

/*                                      
 * Problem ID : LOJ 1088 Points in Segments  
 * Author     : Lirx.t.Una                                      
 * Language   : C++                     
 * CPU	      : 0.364                                      
 * Memory     : 2076                                      
*/ 

#include <algorithm>
#include <iostream>
#include <cstdio>

#define MAXN        100001

using namespace std;

int     a[MAXN];

int
main() {
	
    int     nscn, iscn;
    int     n, k;
    int     x, y;
	
    int     p1, p2;
	
    int     i;
	
    scanf("%d", &nscn);
    iscn = 0;
	
    while ( nscn-- ) {
		
        scanf("%d%d", &n, &k);
		
        for ( i = 0; i < n; i++ )
            scanf("%d", a + i);
		
        printf("Case %d:\n", ++iscn);
        while ( k-- ) {
			
            scanf("%d%d", &x, &y);
			
            p1 = lower_bound(a, a + n, x) - a;
            p2 = upper_bound(a + p1, a + n, y) - a;
			
            printf("%d\n", p2 - p1);
        }
    }
	
    return 0;
}

单词解释:

dimensional:adj, 维度的,空间上的

n dimensional:adj, n维的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值