HDOJ-6621(セグメントツリー二分+)

K番目の最短距離

HDOJ-6621

  • この問題は、ノードに対応するノードのすべての要素を保持し、セグメントツリーを用いて解決することができ、そして昇順ソートヒット
  • 最後に、二分法は、答えを解決します。被写体の絶対値が、それが必要であるため、両者の用途を見出し、そして次に比較Kを減算します
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
int n,m;
int l,r,p,k;
int l1,r1,p1,k1;
int x=0;
int arr[100005];
vector<int> v[400020];//注意这里的空间开4*n
void build(int node,int l,int r){
    v[node].clear();
    for(int i=l;i<=r;i++){
        v[node].push_back(arr[i]);
    }
    sort(v[node].begin(),v[node].end());
    if(l==r){
        return;
    }
    int mid=(l+r)>>1;
    build(node<<1,l,mid);
    build(node<<1|1,mid+1,r);
}
int query(int node,int l,int r,int p,int q,int u){
    if(p<=l&&q>=r){
        vector<int>::iterator it=upper_bound(v[node].begin(),v[node].end(),u);
        int cnt=it-v[node].begin();
        return cnt;
    }
    int ans=0;
    int mid=(l+r)>>1;
    if(p<=mid){
        ans+=query(node<<1,l,mid,p,q,u);
    }
    if(q>mid){
        ans+=query(node<<1|1,mid+1,r,p,q,u);
    }
    return ans;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        x=0;
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&arr[i]);
        }
        build(1,1,n);
        int maxs=*max_element(arr+1,arr+1+n);//这里不能卸载right那里,否则超时
        for(int i=0;i<m;i++){
            scanf("%d%d%d%d",&l1,&r1,&p1,&k1);
            l=l1^x;r=r1^x;p=p1^x;k=k1^x;
            int left=0,right=maxs;//max_element用来求数组中的一个最大值
            while(right>=left){
                int mid=(right+left)>>1;
                int temp=query(1,1,n,l,r,p+mid)-query(1,1,n,l,r,p-mid-1);
                if(temp>=k){
                    right=mid-1;
                }else{
                    left=mid+1;
                }
            }
        printf("%d\n",left);
        x=left;
        //cout<<left<<endl;
        }
    }
    //system("pause");
    return 0;
}

おすすめ

転載: www.cnblogs.com/GarrettWale/p/11319205.html
おすすめ