• 2019 Multi-University Training Contest 4 1008K-th Closest Distance(二分+主席树)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6621

    题目大意:给一个数组,每次给 l ,r, p, k,问区间 [l, r] 的数与 p 的绝对值的第 k小的数是哪个

    解题思路:可以二分mid,然后判断在[l,r]区间内是否刚好有k个数大于等于p-mid,小于等于p+mid,判断的话可以直接用主席树,用主席树可以查找出小于等于某个数的个数,找到小于p+mid的个数-小于等于p-mid-1的个数,即为区间[l,r]内小于等于p+mid且大于p-mid的个数。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=100005;
    int n,m,cnt,root[maxn],a[maxn];
    struct node{
        int l,r,sum;
    }T[maxn*40];
    vector<int> v;
    int getid(int x){
        return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
    }
    void update(int &now,int pre,int l,int r,int pos){
        T[++cnt]=T[pre],T[cnt].sum++,now=cnt;
        if(l==r) return;
        int mid=(l+r)/2;
        if(pos<=mid) update(T[now].l,T[pre].l,l,mid,pos);
        else update(T[now].r,T[pre].r,mid+1,r,pos);
    }
    int query(int l,int r,int x,int y,int k){
        if(l==r) return T[y].sum-T[x].sum;
        int mid=(l+r)/2,ans=0;
        if(k<=mid) ans+=query(l,mid,T[x].l,T[y].l,k);
        else{
            ans+=T[T[y].l].sum-T[T[x].l].sum;
            ans+=query(mid+1,r,T[x].r,T[y].r,k);
        }
        return ans;
    }
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            cnt=0; v.clear();
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)scanf("%d",&a[i]),v.push_back(a[i]);
            sort(v.begin(),v.end()),v.erase(unique(v.begin(),v.end()),v.end());
            for(int i=1;i<=n;i++) update(root[i],root[i-1],1,n,getid(a[i]));
            int tmp=0;
            while(m--){
                int L,R,k,p;
                scanf("%d%d%d%d",&L,&R,&p,&k);
                L^=tmp; R^=tmp; p^=tmp; k^=tmp;
                int l=0,r=1e6+9,ans;
                while(l<=r){
                    int mid=(l+r)/2;
                    int l1=upper_bound(v.begin(),v.end(),p-mid-1)-v.begin(),r1=upper_bound(v.begin(),v.end(),p+mid)-v.begin();
                    int x1,x2;
                    if(l1==0) x1=0;
                    else x1=query(1,n,root[L-1],root[R],l1);
                    if(r1==0) x2=0;
                    else x2=query(1,n,root[L-1],root[R],r1);
                    if(x2-x1>=k){
                        ans=mid;
                        r=mid-1;
                    }else l=mid+1;
                }
                printf("%d
    ",ans);
                tmp=ans;
            }
        }
        return 0;
    }
  • 相关阅读:
    idea中svn代码冲突
    数据库表的连接(Left join , Right Join, Inner Join)用法详解
    @Param注解的用法解析
    spring @Transactional注解参数详解
    数据库的DDL、DML和DCL的区别与理解
    Mybatis:resultMap的使用总结
    Maps.newHashMap 和 new HashMap的区别
    php 个推的例子
    fidder 调接口 的 小常识
    php Memcached
  • 原文地址:https://www.cnblogs.com/zjl192628928/p/11289789.html
Copyright © 2020-2023  润新知