zoukankan      html  css  js  c++  java
  • 2019杭电多校赛第四场 HDU6621 K-th Closest Distance 主席树 二分

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

    题意:T(3)组样例,n(1e5)个数,q(1e5)次查询,查询[l , r] 内, | a[i] - p | 第k大的数,且强制要求在线

    分析:初始的思路是跟着修改,想着用动态主席树来做,但是并不会,而且也很慢,事实上完全可以通过静态主席树来做

    主席树的结点直接就是1e6个值,不需要进行离散化,我们是对每个值都单独统计出现的次数的

    用二分,查询(p-mid,p+mid)中数的个数,具体实现看代码,复杂度为O(q*log(m)*log(m)),查询代码改的有点像线段树区间求和了,可以帮助理解

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> P;
    const int mod=1e9+7;
    const int maxn=1e5+7;
    const int maxm=1e4+7;
    const int  inf=1<<30;
    const int M=1e6;
    const double pi=acos(-1);
    int nodeNum;                                          
    int L[maxn<<6],R[maxn<<6],sum[maxn<<6];                          
    int a[maxn];                                                           
    int T[maxn];                                                                      
    
    int read()                                               
    {                                                         
        int ans=0,flag=1;char ch=getchar();
        while(ch<'0'||ch>'9') {if(ch=='-') flag=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') {ans=(ans<<3)+(ans<<1)+ch-'0';ch=getchar();}
        return ans*flag;
    }                                   
    int update(int pre,int l,int r,int x) //pre为旧树该位置节点的编号
    {
        int num=++nodeNum; 
        L[num]=L[pre];R[num]=R[pre];sum[num]=sum[pre]+1;
        
        if(l!=r)
        {
            int m=(l+r)>>1;
            if(x<=m) L[num]=update(L[pre],l,m,x);
            else R[num]=update(R[pre],m+1,r,x);
        }
        return num;
    }
    
    int query(int u,int v,int l,int r,int pl,int pr) 
    {
        if(l>=pl&&r<=pr) return sum[v]-sum[u];
        int res=0;
        int mid=(l+r)>>1;
        if(pl<=mid) res+=query(L[u],L[v],l,mid,pl,pr);
        if(pr>mid) res+=query(R[u],R[v],mid+1,r,pl,pr);
        return res;
    }
    
    int main(){
        int Test;Test=read();
        while(Test--){
            int n,m;n=read();m=read();
            for(int i=1;i<=n;i++){
                a[i]=read();
                T[i]=update(T[i-1],1,M,a[i]);
            }
            int ans=0;
            while(m--){
                int l,r,p,k;l=read();r=read();p=read();k=read();
                l=l^ans,r=r^ans,p=p^ans,k=k^ans;
                int left=0,right=M;
                while(left<=right){
                    int mid=(left+right)>>1;
                    if(query(T[l-1],T[r],1,M,max(1,p-mid),min(M,p+mid))>=k){
                        ans=mid;
                        right=mid-1;
                    }
                    else left=mid+1;
                }
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    vb.net控件数组的问题
    用SQL语句创建和删除Access数据库中的表;添加列和删除列
    vs2003C#datagrid单行行高设定
    三亚自由人攻略.2009最新
    VB.NET窗口渐淡关闭
    都市男女的30声幽默叹息
    Windows 正版增值验证工具如何取消
    VAB删除Word多余空行
    VBA控制菜单栏上的菜单(如页面设置、打印)
    win7 下安装 adams
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/11298609.html
Copyright © 2011-2022 走看看