2014-01-04 13:06:50Morris

[UVA][二分] 12715 - Watching the Kangaroo

SampleInput
1
3 2
7 15
14 100
1 11
10
120
SampleOutput
Case 1:
3
0


題目描述:
給一堆區間,接著詢問座標 x 可以在哪個區間內左右展開最大。


題目解法:

二分搜尋左右兩端的最大值,然後二分搜尋是否左邊的最大值大於等於右端點。

#include <stdio.h>
#include <algorithm>
using namespace std;
struct Pt {
    int x, y;
    bool operator<(const Pt &a) const {
        if(x != a.x)
            return x < a.x;
        return y > a.y;
    }
};
Pt D[100005];
int Dx[100005];
int dN;
int prefix[100005];
int main() {
    int testcase, cases = 0;
    int n, m;
    int i, j, k, x;
    scanf("%d", &testcase);
    while(testcase--) {
        scanf("%d %d", &n, &m);
        for(i = 0; i < n; i++) {
            scanf("%d %d", &D[i].x, &D[i].y);
            Dx[i] = D[i].x;
        }
        sort(Dx, Dx+n);
        dN = std::unique(Dx, Dx+n) - Dx;
        for(i = 0; i <= dN; i++)
            prefix[i] = 0;
        for(i = 0; i < n; i++) {
            int dx = std::lower_bound(Dx, Dx+dN, D[i].x) - Dx;
            prefix[dx+1] = max(prefix[dx+1], D[i].y);
        }
        for(i = 1; i <= dN; i++)
            prefix[i] = max(prefix[i], prefix[i-1]);
        printf("Case %d:\n", ++cases);
        while(m--) {
            scanf("%d", &x);
            int l = 0, r = x, mid;
            int L, R, maxval, dx;
            int ret = 0;
            while(l <= r) {
                mid = (l+r)/2;
                L = x - mid;
                R = x + mid;
                dx = std::lower_bound(Dx, Dx+dN, L) - Dx;
                if(dx == dN)    dx--;
                if(Dx[dx] > L)    dx--;
                maxval = prefix[dx+1];
                if(maxval >= R)
                    l = mid+1, ret = mid;
                else
                    r = mid-1;
            }
            printf("%d\n", ret);
        }
    }
    return 0;
}