Closest Distance k-small absolute value HDU6621 K-th (Chairman tree number (statistical range of how many) + || half the weight segment tree + half)

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;
}
View Code

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;
}
View Code

 

Guess you like

Origin www.cnblogs.com/shuaihui520/p/11541240.html