Meaning of the questions: to an array, each to l, r, p, k, ask the interval [l, r] k-th small, the absolute value of p as the absolute value of the difference is how much
Analysis: First, let's analyze a single query how to do it:
The data subject has been presented with multiple queries in a prompt us in the data structure to solve this problem, for common processing section segment tree data structure of choice for friends:
I think the key to this question lies in this : we need to go half the answer ans, why? Us observe, for | pa [i] | <= ans equal to p-ans <= a [i ] <= p + ans problem would be transformed into the query [L, R] interval inside the [p-ans, p + ANS] range of a [i] how many. This is obviously subject to the Chairman of the tree;
We understand the principle of the Chairman of the tree is more stars weights tree line, then we put a [i] as the number of index, with a weight of appearing, then we are queries [L, R] numbers are the weights inside the tree line [ p-ans, p + ans] range of a [i] how many.
Chairman of the tree:
#include<bits/stdc++.h> using namespace std; const int N=1e6+10; int tot; int lson[N],rson[N],sum[N],tr[N]; void build(int &rt,int l,int r){ rt=++tot; if(l==r) return ; int mid=(l+r)>>1; build(lson[rt],l,mid); build(rson[rt],mid+1,r); } void updata(int root,int &rt,int p,int l,int r){ rt=++tot; lson[rt]=lson[root],rson[rt]=rson[root]; sum[rt]=sum[root]+1; if(l==r) return ; int mid=(l+r)>>1; if(p<=mid) updata(lson[root],lson[rt],p,l,mid); else updata(rson[root],rson[rt],p,mid+1,r); } int query(int rt_,int rt,int L,int R,int l,int r){ if(l<=L&&R<=r){ return sum[rt_]-sum[rt]; } int mid=(L+R)>>1; int ans=0; if(l<=mid) ans+=query(lson[rt_],lson[rt],L,mid,l,r); if(mid<r) ans+=query(rson[rt_],rson[rt],mid+1,R,l,r); return ans; } int main(){ int _;scanf("%d",&_); while(_--){ int n,m;scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { int x;scanf("%d",&x); updata(tr[i-1],tr[i],x,1,N); } int T=0; for(int i=1;i<=m;i++){ int L,R,p,k; scanf("%d%d%d%d",&L,&R,&p,&k); L^=T,R^=T,p^=T,k^=T; int LL=0,RR=1e6,ans=0; while(LL<=RR){ int mid=(LL+RR)>>1; int l=max(1,p-mid); int r=min(N,p+mid); if(query(tr[R],tr[L-1],1,N,l,r)>=k){ RR=mid-1;ans=mid; } else LL=mid+1; } T=ans; printf("%d\n",ans); } } return 0; }
Weight tree line approach:
To solve the problem still has not changed;
Each node of the segment tree are kept ordered sequence corresponding intervals, e.g., {5,1,2,3,4}, for such a sequence, the root node of the tree represents the segment interval [1,5] node inside there {1,2,3,4,5} sequences that we query p-ans <= a [i] <= p + ans, {1,2,3,4,5} to half the orderly a sequence number is greater than p + ans, number
Greater than p-ans-1, in the subtraction; this clock tree line, really unheard ........
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; vector<int>v[N]; vector<int>::iterator it; int a[N]; void build(int l,int r,int rt){ v[rt].clear(); for(int i=l;i<=r;i++) v[rt].push_back(a[i]); sort(v[rt].begin(),v[rt].end()); if(l==r) return ; int mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); } int query(int L,int R,int rt,int l,int r,int val){ if(l<=L&&R<=r){ it=upper_bound(v[rt].begin(),v[rt].end(),val); return it-v[rt].begin(); } int ans=0; int mid=(L+R)>>1; if(l<=mid) ans+=query(L,mid,rt<<1,l,r,val); if(mid<r) ans+=query(mid+1,R,rt<<1|1,l,r,val); return ans; } int main(){ int _; scanf("%d",&_); while(_--){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,n,1); int L1=0,R1=0,p1=0,k1=0; int T=0; for(int i=1;i<=m;i++){ int L,R,p,k; scanf("%d%d%d%d",&L,&R,&p,&k); L^=T,R^=T,p^=T,k^=T; int LL=0,RR=1e6,ans=0; while(LL<=RR){ int mid=(LL+RR)>>1; int K=query(1,n,1,L,R,p+mid)-query(1,n,1,L,R,p-mid-1); if(K>=k) {RR=mid-1;ans=mid;} else LL=mid+1; } printf("%d\n",ans); T=ans; } } return 0; }