2019杭电多校第四场hdu6621 K-th Closest Distance(二分答案+主席树)

K-th Closest Distance

题目传送门

解题思路

二分答案+主席树

先建主席树,然后二分答案mid,在l和r的区间内查询[p-mid, p+mid]的范围内的数的个数,如果大于k则说明这个范围内存在第k小的数,r=mid,否则不存在,l=mid+1。

代码如下

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;

inline int read(){
    int res = 0, w = 0; char ch = 0;
    while(!isdigit(ch)){
        w |= ch == '-', ch = getchar();
    }
    while(isdigit(ch)){
        res = (res << 3) + (res << 1) + (ch ^ 48);
        ch = getchar();
    }
    return w ? -res : res;
}

const int N = 1000005;

int rt[N], cnt;
struct T{
    int l, r;
    int lch, rch;
    int sum;
}tree[N * 30];

inline int build(int l, int r)
{
    int p = ++cnt;
    tree[p].l = l;
    tree[p].r = r;
    tree[p].lch = tree[p].rch = tree[p].sum = 0;
    if(l == r)
        return p;
    int mid = (l + r) / 2;
    tree[p].lch = build(l, mid);
    tree[p].rch = build(mid + 1, r);
    return p;
}

inline int insert(int k, int x)
{
    int p = ++cnt;
    tree[p].l = tree[k].l;
    tree[p].r = tree[k].r;
    tree[p].lch = tree[k].lch;
    tree[p].rch = tree[k].rch;
    tree[p].sum = tree[k].sum + 1;
    if(tree[k].l == tree[k].r)
        return p;
    int mid = (tree[k].l + tree[k].r) / 2;
    if(x <= mid)
        tree[p].lch = insert(tree[k].lch, x);
    else
        tree[p].rch = insert(tree[k].rch, x);
    return p;
}

int query(int k1, int k2, int l, int r)
{
    if(tree[k1].l >= l && tree[k1].r <= r)
        return tree[k2].sum - tree[k1].sum;
    int mid = (tree[k1].l + tree[k1].r) / 2;
    int m1 = 0, m2 = 0;
    if(l <= mid)
        m1 = query(tree[k1].lch, tree[k2].lch, l, r);
    if(r > mid)
        m2 = query(tree[k1].rch, tree[k2].rch, l, r);
    return m1 + m2;
}

int main()
{
    int _;
    scanf("%d", &_);
    while(_ --){
        int n, m;
        scanf("%d%d", &n, &m);
        rt[0] = build(1, 1e6);
        for(int i = 1; i <= n; i ++){
            int x = read();
            rt[i] = insert(rt[i -1], x);
        }
        int x = 0;
        for(int i = 1; i <= m; i ++){
            int l, r, p, k;
            l = read(), r = read(), p = read(), k = read();
            l ^= x, r ^= x, p ^= x, k ^= x;
            int ll = 0, rr = 1e6;
            int mid = (ll + rr) / 2;
            while(ll < rr){
                if(query(rt[l - 1], rt[r], max(1, p - mid), min(p + mid, 1000000)) >= k)
                    rr = mid;
                else
                    ll = mid + 1;
                mid = (ll + rr) / 2;
            }
            x = mid;
            printf("%d\n", x);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/whisperlzw/p/11280421.html

时间: 2024-08-29 11:11:24

2019杭电多校第四场hdu6621 K-th Closest Distance(二分答案+主席树)的相关文章

2019 杭电多校 第四场

2019 Multi-University Training Contest 4 补题链接:2019 Multi-University Training Contest 4 1001 AND Minimum Spanning Tree (HDU 6614) 题意 给定一个有 \(N\) 个结点的完全图,编号从 \(1\) 到 \(N\).结点 \(x\) 与结点 \(y\) \((1\leq x, y\leq N, x \neq y)\) 的边的权值为 \(x\) 与 \(y\) 按位与的值,求

2019 杭电多校 第五场

2019 Multi-University Training Contest 5 补题链接:2019 Multi-University Training Contest 5 罚时爆炸 自闭场 1004 equation (HDU 6627) 题意: 给定一个整数 \(C\) 和 \(N\) 组 \(a_i,b_i\),求 \(∑_{i=1}^N|a_i\cdot x + b_i| = C\) 的所有解,如果有无穷多个解就输出 -1. 思路 分类讨论 分类讨论去绝对值.根据 \(b_i / a_i

2019 杭电多校 第七场

2019 Multi-University Training Contest 7 补题链接:2019 Multi-University Training Contest 7 1001 A + B = C 题意: 给出 \(a, b, c\),求 \(x, y, z\) 满足 \(a\cdot 10^x + b\cdot 10^y = c\cdot 10^z\).\(a, b, c \le 10^{100000}\). 题解: 补零到 \(a, b, c\) 长度相等之后,可能的情况只有四种: \

2019 杭电多校 第八场

2019 Multi-University Training Contest 8 补题链接:2019 Multi-University Training Contest 8 1003 Acesrc and Good Numbers HDU 6659 题意 定义 \(f(d, n)\) 为十进制下 \(1\) 到 \(n\) 所有数的数位中数字 \(d\) 出现的次数.给定 \(x\),找出最大的 \(n(n \le x)\) 满足 \(f(d, n) = n\). 题解 看到了一个神仙做法. 显

2019 杭电多校 第六场

2019 Multi-University Training Contest 6 补题链接:2019 Multi-University Training Contest 6 1002 Nonsense Time (HDU 6635) 题意 给定包含 \(n\) 个不同数字的排列 \(p\).一开始所有数字都冻住.再给出一个长度为 \(n\) 的数组 \(k\),\(k[i]\) 表示 \(p[k[i]]\) 在第 \(i\) 时刻解冻.输出 \(n\) 个数,表示第 \(i\) 个时刻数组 \(

2019 杭电多校 第三场

2019 Multi-University Training Contest 3 补题链接:2019 Multi-University Training Contest 3 1002 Blow up the city (HDU-6604) 题意 给定 \(n\) 个点和 \(m\) 条边的有向无环图,给出 \(q\) 次询问,每个询问给出 \(a\) 和 \(b\),求有多少个点,满足该点删去后 \(a\) 和 \(b\) 中至少一个点不能到达出度为 \(0\) 的点. 题解 支配树/灭绝树 拓

2019杭电多校第三场 1004 Distribution of books

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6606 考虑二分答案,我们二分一个值\(x\),那么要怎么来验证这个答案是否可行,考虑dp求解,设\(dp[i]\)为前i个在答案为\(x\)的情况下划分最最多组数,那么若\(dp[n] \geq k\) 则这个x可行, 很显然可以看出\(x\)是单调的,所以二分. \[dp[i] = max(dp[j]) + 1 (sum[i] - sum[j-1] \leq x)\] 如果直接采用暴力枚举的话复杂

2019杭电多校第三场 1008 K-th Closest Distance

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=6621 考虑主席树,我们先将所有值离散化之后建主席树.对于每个查询\(s,t,p,k\) 我们考虑二分一个值\(mid\),考虑当前区间内,\([p-mid, p+mid]\)的值有多少个,很显然这是符合单调性的,那么我们只需要每次判断即可.时间复杂度\(O(nlog^2n)\) #include <bits/stdc++.h> #define pii pair<int, int> #d

2019杭电多校第六场hdu6638 Snowy Smile(线段树+枚举)

Snowy Smile 题目传送门 解题思路 先把y离散化,然后把点按照x的大小进行排序,我们枚举每一种x作为上边界,然后再枚举其对应的每一种下边界.按照这种顺序插入点,这是一个压维的操作,即在线段树中的y位置加上其w,并利用线段树来更新动态的最大子段和. 代码如下 #include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; const int N = 2005; stru