zoukankan      html  css  js  c++  java
  • HDU Multi-University Training Contest 4 HDU 6621 K-th Closest Distance

    杭电多校第4场08题。

    主席树+二分

    看到题目应该是用主席树。当时看到k最大只有169,就想着先找到p在区间内的排名,然后暴力查找,写了好久,代码有点难调,交上去就是RE,应该是WA了,导致异或那步错了,进而导致RE。

    题解是主席树加二分,二分答案mid,然后用主席树查询区间l-r内,值域在[p-mid,p+mid]内的点的个数,如果个数大于k个,说明我们的mid选大了,然后就要减小mid,否则增大mid,二分即可。

    #include <bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int M = 1e6 + 10;
    //const int mx = 1e6;
    struct tree{
        int cnt, lc, rc;
    }T[(M << 6)];
    int root[N], a[N], b[N];
    int n, m, q, tot;
    void build(int &rt, int l, int r)//建立一颗空树
    {
        rt = ++tot;
        T[rt].cnt = 0;
        T[rt].lc = T[rt].rc = 0;
        if (l == r) return;
        int mid = (l + r) >> 1;
        build(T[rt].lc, l, mid);
        build(T[rt].rc, mid + 1, r);
    }
    void insert(int l, int r, int &cur, int pre, int pos)
    {
        T[++tot] = T[pre];
        cur = tot;
        T[cur].cnt++;
        if (l == r) return;
        int mid = (l + r) >> 1;
        if (pos <= mid) insert(l, mid, T[cur].lc, T[pre].lc, pos);
        else insert(mid + 1, r, T[cur].rc, T[pre].rc, pos);
    }
    int query(int l, int r, int x, int y, int k)
    {
        if (r <= k) return T[y].cnt - T[x].cnt;
        if (l == r){
            return T[y].cnt - T[x].cnt;
        }
        int s = T[T[y].lc].cnt - T[T[x].lc].cnt;
        int mid = (l + r) >> 1;
        if (k <= mid){
            return query(l, mid, T[x].lc, T[y].lc, k);
        }
        else{
            return s + query(mid + 1, r, T[x].rc, T[y].rc, k);
        }
    }
    int max(int a, int b)
    {
        return a > b ? a : b;
    }
    int main()
    {
        int T;
        scanf("%d", &T);
        for (int t = 1; t <= T; t++)
        {
            int mx = 0;
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= n; i++)
                scanf("%d", &a[i]),mx=max(mx,a[i]);
            tot = 0;
            build(root[0], 1, mx);
            for (int i = 1; i <= n; i++)
                insert(1, mx, root[i], root[i - 1], a[i]);
            int lst=0;
            while (m--)
            {
                int l, r, p, k;
                scanf("%d%d%d%d", &l, &r, &p, &k);
                l ^= lst, r ^= lst, k ^= lst, p ^= lst;
                int L=0, R = 1e6;
                while (L < R)
                {
                    int mid = (L + R) >> 1;
                    int cnt = query(1, mx, root[l - 1], root[r], p + mid);
                    if (p - mid - 1>0) cnt -= query(1, mx, root[l - 1], root[r], p - mid - 1);
                    if (cnt >= k) R = mid;
                    else L = mid + 1;
                }
                printf("%d
    ", lst = L);
            }
        }
        return 0;
    }
  • 相关阅读:
    大话数据结构笔记
    zsh安装教程
    Matlab安装教程
    7-16 插入排序还是归并排序 (25 分)
    7-14 插入排序还是堆排序 (25 分)
    7-14 二叉搜索树的最近公共祖先 (30 分)
    7-11 笛卡尔树 (25 分)
    中缀转换为后缀和前缀
    7-15 水果忍者 (30 分)
    兔子的区间密码(思维)
  • 原文地址:https://www.cnblogs.com/xiaoguapi/p/11278478.html
Copyright © 2011-2022 走看看