zoukankan      html  css  js  c++  java
  • K-th Closest Distance

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

    K-th Closest Distance

    Time Limit: 20000/15000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
    Total Submission(s): 2426    Accepted Submission(s): 871


    Problem Description
    You have an array: a1, a2, �, an and you must answer for some queries.
    For each query, you are given an interval [L, R] and two numbers p and K. Your goal is to find the Kth closest distance between p and aL, aL+1, ..., aR.
    The distance between p and ai is equal to |p - ai|.
    For example:
    A = {31, 2, 5, 45, 4 } and L = 2, R = 5, p = 3, K = 2.
    |p - a2| = 1, |p - a3| = 2, |p - a4| = 42, |p - a5| = 1.
    Sorted distance is {1, 1, 2, 42}. Thus, the 2nd closest distance is 1.
     
    Input
    The first line of the input contains an integer T (1 <= T <= 3) denoting the number of test cases.
    For each test case:
    冘The first line contains two integers n and m (1 <= n, m <= 10^5) denoting the size of array and number of queries.
    The second line contains n space-separated integers a1, a2, ..., an (1 <= ai <= 10^6). Each value of array is unique.
    Each of the next m lines contains four integers L', R', p' and K'.
    From these 4 numbers, you must get a real query L, R, p, K like this: 
    L = L' xor X, R = R' xor X, p = p' xor X, K = K' xor X, where X is just previous answer and at the beginning, X = 0.
    (1 <= L < R <= n, 1 <= p <= 10^6, 1 <= K <= 169, R - L + 1 >= K).
     
    Output
    For each query print a single line containing the Kth closest distance between p and aL, aL+1, ..., aR.
     
    Sample Input
    1 5 2 31 2 5 45 4 1 5 5 1 2 5 3 2
     
    Sample Output
    0 1
     
    Source
    题目大意:T组样例,N个数 M次询问,L,R,P,K  问你L,R区间内 距离P第K近的距离是多少
    思路:比赛的时候没啥思路,没写,看题解发现,主席树可以求区间内<=K的数有多少个  但是我们要求的是与某个值相减绝对值第K小啊,这有什么关系吗?
    假设我们知道答案是几,那么此时求出来L,R区间内的数与P相减第K小是不是就是我们这个答案呢? 显然是的,但是问题是我们不知道答案啊
    这就是二分的思想了,二分答案,查询范围在P-ans,P+ans之间的数有多少个,如果个数大于等于K的话,证明我们的ans还可以减小,一直这样下去
    就会得到正确的答案了
    看代码:
    #include<iostream>
    #include<vector>
    #include<cstdio>
    #include<algorithm>
    #include<math.h>
    using namespace std;
    typedef long long LL;
    const int maxn=1e5+5;
    int N,M;
    int sz,cnt=0,sum=0;
    int root[maxn],a[maxn],v[maxn];
    int L,R,P,K,X=0;
    struct Node
    {
        int l,r,sum;
        Node()
        {
            l=r=sum=0;
        }
    }T[maxn<<6];
    void Init()
    {
        cnt=0;root[0]=0;T[cnt].l=T[cnt].r=T[cnt].sum=0;X=0;
    }
    void Read(int &n)//只能读入整数
    {
        n=0;
        int f=1;//用于记录正负
        char ch=getchar();
    
        while(ch<'0'||ch>'9')//
        {
            if(ch=='-') f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')//下面两种用法都可以
        {
            //n=(n<<1)+(n<<3)+(ch-'0');//
            n=(n<<1)+(n<<3)+(ch^48);//相当于  x*10+ch-'0';
            ch=getchar();
        }
        n=n*f;//切记乘以f  (记录的是+ -)
        return ;
    }
    void Update(int l,int r,int &x,int y,int pos)
    {
        T[++cnt]=T[y];T[cnt].sum++;x=cnt;
        if(l==r) return ;
        int mid=(l+r)>>1;
        if(pos<=mid) Update(l,mid,T[x].l,T[y].l,pos);
        else Update(mid+1,r,T[x].r,T[y].r,pos);
    }
    int getid(int x)
    {
        return lower_bound(v+1,v+1+sz,x)-(v);
    }
    void Query(int l,int r,int x,int y,int h)
    {
    //    cout<<"l:"<<l<<" r:"<<r<<" sum:"<<sum<<endl;
        if(l==r)
        {
            if(h>=v[l]) sum+=T[x].sum-T[y].sum;
            return ;
        }
        int mid=(l+r)>>1;
        if(h<=v[mid]) Query(l,mid,T[x].l,T[y].l,h);
        else
        {
            sum+=T[T[x].l].sum-T[T[y].l].sum;
            Query(mid+1,r,T[x].r,T[y].r,h);
        }
    }
    bool judge(int x)
    {
        sum=0;Query(1,sz,root[R],root[L-1],P+x);
        int sum1=sum;
        sum=0;Query(1,sz,root[R],root[L-1],P-x-1);
        int sum2=sum;
        return sum1-sum2>=K;
    }
    int main()
    {
        int T;
    //    scanf("%d",&T);
    Read(T);
        int ca=1;
        while(T--)
        {
            Init();
    //        scanf("%d%d",&N,&M);
    Read(N);Read(M);
            for(int i=1;i<=N;i++)
            {
                scanf("%d",&a[i]);v[i]=a[i];
            }
            sort(v+1,v+1+N);sz=unique(v+1,v+1+N)-(v+1);
    //        for(int i=1;i<=sz;i++) cout<<v[i]<<" ";cout<<endl;
    //        for(int i=1;i<=N;i++) cout<<getid(a[i])<<" ";cout<<endl;
            for(int i=1;i<=N;i++) Update(1,sz,root[i],root[i-1],getid(a[i]));
            while(M--)
            {
                sum=0;
    //            scanf("%d%d%d%d",&L,&R,&P,&K);
    Read(L);Read(R);Read(P);Read(K);
                L^=X;R^=X;P^=X;K^=X;
                int l=0,r=1e6,ans;
                while(l<=r)//二分答案
                {
                    int mid=(l+r)>>1;
                    if(judge(mid))
                    {
                        ans=mid;r=mid-1;
                    }
                    else l=mid+1;
                }
                printf("%d
    ",ans);
                X=ans;
            }
        }
        return 0;
    }
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    LeetCode #1021. Remove Outermost Parentheses 删除最外层的括号
    使用Maven运行测试提示Module sdk 1.5的解决方法
    Map.Entry使用详解
    c++基础(一)
    Python_正则表达式
    使用PIL生成验证码
    OpenCV_图像平滑
    OpenCV—图像阈值
    OpenCV形状变换
    使用OpenCV读写图片
  • 原文地址:https://www.cnblogs.com/caijiaming/p/11289099.html
Copyright © 2011-2022 走看看