HDU 6621 K-th Closest Distance

K-th Closest Distance

Time Limit: 20000/15000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)

Problem Description

You have an array: a1, a2, , an and you must answer for some queries.
For each query, you are given an interval [L, R] and two numbers p and K. Your goal is to find the Kth closest distance between p and aL, aL+1, …, aR.
The distance between p and ai is equal to |p - ai|.
For example:
A = {31, 2, 5, 45, 4 } and L = 2, R = 5, p = 3, K = 2.
|p - a2| = 1, |p - a3| = 2, |p - a4| = 42, |p - a5| = 1.
Sorted distance is {1, 1, 2, 42}. Thus, the 2nd closest distance is 1.

Input

The first line of the input contains an integer T (1 <= T <= 3) denoting the number of test cases.
For each test case:
冘The first line contains two integers n and m (1 <= n, m <= 10^5) denoting the size of array and number of queries.
The second line contains n space-separated integers a1, a2, …, an (1 <= ai <= 10^6). Each value of array is unique.
Each of the next m lines contains four integers L’, R’, p’ and K’.
From these 4 numbers, you must get a real query L, R, p, K like this:
L = L’ xor X, R = R’ xor X, p = p’ xor X, K = K’ xor X, where X is just previous answer and at the beginning, X = 0.
(1 <= L < R <= n, 1 <= p <= 10^6, 1 <= K <= 169, R - L + 1 >= K).

Output

For each query print a single line containing the Kth closest distance between p and aL, aL+1, …, aR.

Sample Input

1
5 2
31 2 5 45 4
1 5 5 1
2 5 3 2

Sample Output

0
1

题意:

给你一组数字,题目给你x, y, p, k,让你求出在[x, y]这个区间里面每个值与p相减的绝对值的第k个小。每次的x,y,p,k要与上次答案异或。

思路:

看到这类题目第一个想的一般就是主席树了,
1 首先就是建立一个主席树,因为这次没有办法初始化,所以就是从要求最大值了。
2 在查询的时候,在区间[p- mid, p + mid]中有多少个数,这些数就是个比mid来的小的数,这个时候和k进行比较,然后不断二分最后得出答案。

#include 
#include 
#include 
#include 
using namespace std;
const int maxn = 1e+5 + 10;
struct NODE {
    int l;
    int r;
    int sum;
};
NODE T[maxn * 50];
int root[maxn], a[maxn];
int cnt = 0;
void Updata(int l, int r, int &x, int y, int pos) {
    T[++cnt] = T[y];
    T[cnt].sum++;
    x = cnt;
    if (l == r) return ;
    int mid = (l + r) >> 1;
    if (mid >= pos) Updata(l, mid, T[x].l, T[y].l, pos);
    else Updata(mid + 1, r, T[x].r, T[y].r, pos);
}
int Query(int ll, int rr, int l, int r, int x, int y) {
    if (ll <= l && rr >= r) return T[y].sum - T[x].sum;
    int mid = (l + r) >> 1, ans = 0;
    if (ll <= mid) ans += Query(ll, rr, l, mid, T[x].l, T[y].l);
    if (rr > mid) ans += Query(ll, rr, mid + 1, r, T[x].r, T[y].r);
    return ans;
}
int main() {
    int n, t, m;
    scanf("%d", &t);
    while (t--) {
        int Max = 0, X = 0;
        cnt = 0;
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            Max = max(Max, a[i]);
        }
        for (int i = 1; i <= n; i++) Updata(1, Max, root[i], root[i - 1], a[i]);
        while (m--) {
            int x, y, k, p;
            scanf("%d %d %d %d", &x, &y, &p, &k);
            x ^= X;
            y ^= X;
            p ^= X;
            k ^= X;
            int l = 0, r = 1e+6;
            while (r > l) {
                int mid = (l + r) >> 1;
                if (Query(max(1, p - mid), min(p + mid, Max), 1, Max, root[x - 1], root[y]) >= k) r = mid;
                else l = mid + 1;
            }
            X = r;
            printf("%d\n", r);
        }
    }
    return 0;
}

你可能感兴趣的:(HDU)