K-th Closest Distance
题意:给定长度为\(n\)的数列,现有m次查询,每组询问给\(l,r,p,k\),问对\(l<=i<=r\),\(|p-a[i]|\)的第k小值。数据强制在线。
题解:二分答案ans,用主席树查询\(a[l]\)到\(a[r]\)之间\([p-ans,p+ans]\)的个数,个数为k即为答案。
由于强制在线,所以建主席树不能离散化。可以动态空间直接建树。
#include<bits/stdc++.h> using namespace std; const int maxn=100005; int n,m; const int N=1e6; struct node{ int ls,rs,sum; }; node tree[maxn*22]; int rt[maxn],tot=0; int update(int l,int r,int x,int pre){ int now=++tot; tree[now]=tree[pre]; if(l==r){ tree[now].sum++; return now; } int mid=(l+r)>>1; if(x>mid) tree[now].rs=update(mid+1,r,x,tree[pre].rs); else tree[now].ls=update(l,mid,x,tree[pre].ls); tree[now].sum++; return now; } int ask(int l,int r,int il,int ir,int root1,int root2){ if(r<il||l>ir) return 0; if(l>=il&&r<=ir) return tree[root2].sum-tree[root1].sum; int mid=(l+r)>>1; return ask(l,mid,il,ir,tree[root1].ls,tree[root2].ls)+ask(mid+1,r,il,ir,tree[root1].rs,tree[root2].rs); } int jud(int len,int p,int rt1,int rt2){ int l=max(1,p-len),r=min(N,p+len); return ask(1,N,l,r,rt1,rt2); } int solve(int l,int r,int p,int k){ int rt1=rt[l-1],rt2=rt[r]; int ll=0,rr=N; while(ll<rr){ int mid=(ll+rr)>>1; if(jud(mid,p,rt1,rt2)>=k) rr=mid; else ll=mid+1; } return ll; } int main(){ int T; cin >> T; while(T--){ tot=0; tree[0].sum=tree[0].ls=tree[0].rs=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { int x; scanf("%d",&x); rt[i]=update(1,N,x,rt[i-1]); } int las=0; while(m--){ int l,r,p,k; scanf("%d%d%d%d",&l,&r,&p,&k); l^=las; r^=las; p^=las; k^=las; printf("%d\n",las=solve(l,r,p,k)); } } return 0; }
来源:https://www.cnblogs.com/vege-chicken-rainstar/p/11544406.html