HDU 6621-K-th Closest Distance

Question: Give you a sequence of n numbers, m times of inquiry, each time you find a point in the interval [l, r] which is nearest to the point p to the k, and output the K distance.

Thoughts: We use the chairman tree to count the number of occurrences of each number in the interval, and then dichotomize the answer to check whether the number of [p - mid, p + mid] is greater than or equal to k in the interval. In some cases, it will prove that the current answer is feasible, and the idea is still very clever.

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
int sum[maxn << 5], root[maxn], ls[maxn << 5], rs[maxn << 5];
int a[maxn], b[maxn];
int n, m, tot, len;

int update(int k, int l, int r, int rt)
{
    int now = ++tot;
    ls[now] = ls[rt], rs[now] = rs[rt], sum[now] = sum[rt] + 1;
    if(l == r)
        return now;
    int mid = (l + r) >> 1;
    if(k <= mid)
        ls[now] = update(k, l, mid, ls[now]);
    else
        rs[now] = update(k, mid + 1, r, rs[now]);
    return now;
}
int query(int u, int v, int l, int r,int ql,int qr) //Number of query intervals
{
    if(ql <= l && r <= qr)
        return sum[v] - sum[u];
    int mid = (l + r) >> 1;
    int res = 0;
    if(ql <= mid)
        res += query(ls[u], ls[v], l, mid, ql, qr);
    if(qr > mid)
        res += query(rs[u], rs[v], mid + 1, r, ql, qr);
    return res;
}
void init()
{
    tot = 0, len = 1e6;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i)
    {
        scanf("%d", &a[i]);
    }
    root[0] = 0;
    for(int i = 1; i <= n; ++i)
        root[i] = update(a[i], 1, len, root[i - 1]);
}

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        init();
        int l, r, p, k, x = 0;
        while(m--)
        {
            scanf("%d%d%d%d", &l, &r, &p, &k);
            l ^= x, r ^= x, p ^= x, k ^= x;
            int L = 0, R = len;
            while(L <= R) //Two points difference
            {
                int mid = (L + R) >> 1;
                if(query(root[l - 1], root[r], 1, len, max(1, p - mid), min(len, p + mid)) >= k)
                    R = mid - 1, x = mid;
                else
                    L = mid + 1;
            }
            printf("%d\n", x);
        }
    }

    return 0;
}

 

Posted by DynV on Tue, 08 Oct 2019 16:11:22 -0700