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 小绝对值(主席树(统计范围的数有多少个)+ 二分 || 权值线段树+二分)