2019杭电多校赛第四场 HDU6621 K-th Closest Distance 主席树 二分
Posted qingjiuling
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019杭电多校赛第四场 HDU6621 K-th Closest Distance 主席树 二分相关的知识,希望对你有一定的参考价值。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6621
题意:T(3)组样例,n(1e5)个数,q(1e5)次查询,查询[l , r] 内, | a[i] - p | 第k大的数,且强制要求离线化
分析:初始的思路是跟着修改,想着用动态主席树来做,但是并不会,而且也很慢,事实上完全可以通过静态主席树来做
主席树的结点直接就是1e6个值,不需要进行离散化,我们是对每个值都单独统计出现的次数的
用二分,查询(p-mid,p+mid)中数的个数,具体实现看代码,复杂度为O(q*log(m)*log(m)),查询代码改的有点像线段树区间求和了,可以帮助理解
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> P; const int mod=1e9+7; const int maxn=1e5+7; const int maxm=1e4+7; const int inf=1<<30; const int M=1e6; const double pi=acos(-1); int nodeNum; int L[maxn<<6],R[maxn<<6],sum[maxn<<6]; int a[maxn]; int T[maxn]; int read() int ans=0,flag=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘) if(ch==‘-‘) flag=-1;ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘) ans=(ans<<3)+(ans<<1)+ch-‘0‘;ch=getchar(); return ans*flag; int update(int pre,int l,int r,int x) //pre为旧树该位置节点的编号 int num=++nodeNum; L[num]=L[pre];R[num]=R[pre];sum[num]=sum[pre]+1; if(l!=r) int m=(l+r)>>1; if(x<=m) L[num]=update(L[pre],l,m,x); else R[num]=update(R[pre],m+1,r,x); return num; int query(int u,int v,int l,int r,int pl,int pr) if(l>=pl&&r<=pr) return sum[v]-sum[u]; int res=0; int mid=(l+r)>>1; if(pl<=mid) res+=query(L[u],L[v],l,mid,pl,pr); if(pr>mid) res+=query(R[u],R[v],mid+1,r,pl,pr); return res; int main() int Test;Test=read(); while(Test--) int n,m;n=read();m=read(); for(int i=1;i<=n;i++) a[i]=read(); T[i]=update(T[i-1],1,M,a[i]); int ans=0; while(m--) int l,r,p,k;l=read();r=read();p=read();k=read(); l=l^ans,r=r^ans,p=p^ans,k=k^ans; int left=0,right=M; while(left<=right) int mid=(left+right)>>1; if(query(T[l-1],T[r],1,M,max(1,p-mid),min(M,p+mid))>=k) ans=mid; right=mid-1; else left=mid+1; printf("%d\n",ans); return 0;
以上是关于2019杭电多校赛第四场 HDU6621 K-th Closest Distance 主席树 二分的主要内容,如果未能解决你的问题,请参考以下文章
2019杭电多校第三场 1008 K-th Closest Distance
HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分)