Time Limit: 20000/15000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
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.
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).
For each query print a single line containing the Kth closest distance between p and aL, aL+1, …, aR.
1
5 2
31 2 5 45 4
1 5 5 1
2 5 3 2
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;
}