2019杭电多校赛第四场 HDU6621 K-th Closest Distance 主席树 二分

Posted qingjiuling

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",ans);
        
    
    return 0;

 

以上是关于2019杭电多校赛第四场 HDU6621 K-th Closest Distance 主席树 二分的主要内容,如果未能解决你的问题,请参考以下文章

2019 杭电多校 第四场

2019杭电多校第三场 1008 K-th Closest Distance

HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分)

2020杭电多校第四场 Go Running 最小点覆盖等于二分图最大匹配数

杭电多校第四场 E Matrix from Arrays

杭电多校第四场 1003 Contest of Rope Pulling(随机化+动态规划)