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
建立好主席树,然后每次查询对距离二分就好了~PS(注意这个傻逼题要求每次l,r,p,k都要对上一次答案进行异或,wa了一年因为这个有点的没得,真的烦)。
#include
using namespace std;
const int maxn = 100005;
const int M = maxn * 30;
int n, q, tot, m;
int a[maxn], t[maxn];
int T[maxn], lson[M], rson[M], c[M];
void Init_hash() {
for (int i = 1; i <= n; i++)
t[i] = a[i];
sort(t + 1, t + 1 + n);
m = unique(t + 1, t + 1 + n) - t - 1;
}
int build(int l, int r) {
int root = tot++;
c[root] = 0;
if (l != r) {
int mid = (l + r) >> 1;
lson[root] = build(l, mid);
rson[root] = build(mid + 1, r);
}
return root;
}
int update(int root, int pos, int val) {
int newroot = tot++, tmp = newroot;
c[newroot] = c[root] + val;
int l = 1, r = m;
while (l < r) {
int mid = (l + r) >> 1;
if (pos <= mid) {
lson[newroot] = tot++; rson[newroot] = rson[root];
newroot = lson[newroot]; root = lson[root];
r = mid;
}
else {
rson[newroot] = tot++; lson[newroot] = lson[root];
newroot = rson[newroot]; root = rson[root];
l = mid + 1;
}
c[newroot] = c[root] + val;
}
return tmp;
}
int Hash(int x) {
return lower_bound(t + 1, t + 1 + m, x) - t;
}
int query(int left_root, int right_root, int l, int r, int L, int R) {
if (L <= t[l] && t[r] <= R) {
return c[right_root] - c[left_root];
}
int mid = (l + r) >> 1, sum = 0;
if (L <= t[mid]) {
sum += query(lson[left_root], lson[right_root], l, mid, L, R);
}
if (R >= t[mid + 1]) {
sum += query(rson[left_root], rson[right_root], mid + 1, r, L, R);
}
return sum;
}
int main() {
int te; scanf("%d", &te);
while (te--) {
scanf("%d%d", &n, &q);
tot = 0;
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
Init_hash();
T[0] = build(1, m);
for (int i = 1; i <= n; i++) {
int pos = Hash(a[i]);
T[i] = update(T[i - 1], pos, 1);
}
int re = 0;
while (q--) {
int l, r, k, p;
scanf("%d%d%d%d", &l, &r, &p, &k);
l ^= re; r ^= re; p ^= re; k ^= re;
int li = 0, ri = 1000005, ans = -1;
while (li <= ri) {
int mid = (li + ri) >> 1;
int limit = p - mid, rimit = p + mid;
int res = query(T[l - 1], T[r], 1, m, limit, rimit);
if (res >= k) {
ans = mid;
ri = mid - 1;
}
else li = mid + 1;
}
printf("%d\n", ans);
re = ans;
}
}
return 0;
}