HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分)

Posted buerdepepeqi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分)相关的知识,希望对你有一定的参考价值。

HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分)

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6621

题意:

给你n个数,有m次询问

每次问你在区间[l,r]内 第k小的|\(a_i-p\)|是多少

题解:

主席树+二分

每次二分答案

如果p+mid到p-mid的值的个数大于k个的话,mid值就是可行了,然后缩小区间往左找即可

因为保证有解,所以二分出来的mid值就是答案了

query查的是权值在区间[p-mid,p+mid]内数的个数

主席树的sum就是用来统计权值个数的

注意不要被k给坑了,枚举第k小的数会T到爆的(QAQ)

AC单组复杂度分析 :1e5*log(1e6)*log(1e6);

TLE单组复杂度分析:1e5*169*2*log(1e6);

代码:

#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double Pi = acos(-1);
LL gcd(LL a, LL b) 
    return b ? gcd(b, a % b) : a;

LL lcm(LL a, LL b) 
    return a / gcd(a, b) * b;

double dpow(double a, LL b) 
    double ans = 1.0;
    while(b) 
        if(b % 2)ans = ans * a;
        a = a * a;
        b /= 2;
     return ans;

LL quick_pow(LL x, LL y) 
    LL ans = 1;
    while(y) 
        if(y & 1) 
            ans = ans * x % mod;
         x = x * x % mod;
        y >>= 1;
     return ans;

struct Tree 
    int l, r, sum;
 T[maxn * 40];
int cnt, n, m;
int a[maxn];
int root[maxn];
void update(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(pos <= mid) update(l, mid, T[x].l, T[y].l, pos);
    else update(mid + 1, r, T[x].r, T[y].r, pos);

int query(int l, int r, int x, int y, int k) 
    if(k==0) return 0;
    if(l == r) return T[y].sum - T[x].sum;
    int mid = (l + r) >> 1;
    if (k <= mid)return query(l, mid, T[x].l, T[y].l, k);
    else 
        int ans = query(mid + 1, r, T[x].r, T[y].r, k);
        ans += T[T[y].l].sum - T[T[x].l].sum;
        return ans;
    

int main() 

    int T;
    scanf("%d", &T);
    while(T--) 
        cnt = 0;
        scanf("%d%d", &n, &m);

        for(int i = 1; i <= n; i++) 
            scanf("%d", &a[i]);
        
        int N = 1000000;
        for(int i = 1; i <= n; i++) 
            update(1, N, root[i], root[i - 1], a[i]);
        
        int x, y, p, k;
        int ans = 0;
        for(int i = 1; i <= m; i++) 
            scanf("%d%d%d%d", &x, &y, &p, &k);
            x ^= ans;
            y ^= ans;
            if(x > y) swap(x, y);
            p ^= ans;
            k ^= ans;
            int l = 0, r = N;
            while(l <= r) 
                int mid = (l + r) >> 1;
                int R = min(N, p + mid);
                int L = max(0, p - mid - 1);
                if(query(1, N, root[x - 1], root[y], R) -
                        query(1, N, root[x - 1], root[y], L) >= k) 
                    ans = mid;
                    r = mid - 1;
                 else 
                    l = mid + 1;
                
            
            /*
             while (L <= R) 
                mid = (L + R) >> 1;
                if (query(1, N, root[l - 1], root[r], min(p + mid, N)) -
                    query(1, N, root[l - 1], root[r], max(p - mid - 1, 0)) >= k)
                    ans = mid, R = mid - 1;
                else L = mid + 1;
            */
            printf("%d\n", ans);
        
    
    return 0;

以上是关于HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分)的主要内容,如果未能解决你的问题,请参考以下文章

[hdu-6621]K-th Closest Distance 主席树 线段树 2019 多校4

2019杭电多校赛第四场 HDU6621 K-th Closest Distance 主席树 二分

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

HDU6621 K-th Closest Distance 第 k 小绝对值(主席树(统计范围的数有多少个)+ 二分 || 权值线段树+二分)

K-th Closest Distance

K-th Closest Distance