• Chika and Friendly Pairs(莫队+树状数组+离散化+预处理上下界)


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

    Chika and Friendly Pairs

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
    Total Submission(s): 160    Accepted Submission(s): 52


    Problem Description
    Chika gives you an integer sequence a1,a2,,an and m tasks. For each task, you need to answer the number of "friendly pairs" in a given interval.

    friendly pair: for two integers ai and aj, if i<j and the absolute value of aiaj is no more than a given constant integer K, then (i,j) is called a "friendly pair".A friendly pair (i,j) in a interval [L,R] should satisfy Li<jR.
     
    Input
    The first line contains 3 integers n (1n27000)m (1m27000) and K (1K109), representing the number of integers in the sequence a, the number of tasks and the given constant integer.
    The second line contains n non-negative integers, representing the integers in the sequence a. Every integer of sequence a is no more than 109.
    Then m lines follow, each of which contains two integers LR (1LRn). The meaning is to ask the number of "friendly pairs" in the interval [L,R]
     
    Output
    For each task, you need to print one line, including only one integer, representing the number of "friendly pairs" in the query interval.
     
    Sample Input
    7 5 3
    2 5 7 5 1 5 6
    6 6
    1 3
    4 6
    2 4
    3 4
     
    Sample Output
    0 2 1 3 1
     
    Source
     
    Recommend
    liuyiding   |   We have carefully selected several similar problems for you:  6543 6542 6541 6540 6539 
     
    题意:找区间里a[i]-a[j]<=K的对数  i<j
    思路:n和m都是27000  也就是2*10^4   1秒在10^7左右  所以我们还有10^3  普通莫队的复杂度是n^(3/2)  算一下27000当做25000的话 那么复杂度大概就是10^6  还有10可以用  显然用树结构来
    维护求区间对数  树状数组复杂度log(n)  所以差不多就是10^7左右   果然是邀请赛的题,时间卡的是真的紧,,一点不让你浪费。 如果我们每次都用lower_bound和upperbound去找上下界
    超时。。。  需要预处理上下界  这样就可以A这道题了
    看代码:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const LL mod=1e9+7;
    const LL INF=1e9+7;
    const int maxn=27000+50;
    LL N,M,K;
    LL a[maxn],b[maxn];
    LL c[maxn];
    LL ans[maxn];
    LL up[maxn],low[maxn];
    LL block;
    LL len;
    struct query
    {
        LL l,r,num;
    }q[maxn];
    bool cmp(const query x,const query y)
    {
        if(x.l/block==y.l/block) return x.r<y.r;
        return x.l<y.l;
    }
    int lowbit(int x)
    {
        return x&(-x);
    }
    int sea(LL x)//寻找大小为x的数在b数组中的下标
    {
        int l=1,r=len;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(b[mid]==x) return mid;
            else if(b[mid]>x)
            {
                r=mid-1;
            }
            else l=mid+1;
        }
    }
    void update(LL x,int add)
    {
        while(x<=27000)
        {
            c[x]+=add;
            x+=lowbit(x);
        }
    }
    LL Query(LL x)
    {
        LL ret=0;
        while(x>0)
        {
            ret+=c[x];
            x-=lowbit(x);
        }
        return ret;
    }
    int main()
    {
        scanf("%lld%lld%lld",&N,&M,&K);
        block=sqrt(N);
        for(int i=1;i<=N;i++)
        {
            scanf("%lld",&a[i]);
            b[i]=a[i];
        }
    //    sort(a+1,a+1+N,cmp);
        sort(b+1,b+N+1);
        len=unique(b+1,b+N+1)-(b+1);//去重
        for(int i=1;i<=M;i++)
        {
            scanf("%lld%lld",&q[i].l,&q[i].r);
            q[i].num=i;
        }
        sort(q+1,q+M+1,cmp);
    
        for(int i=1;i<=N;i++)
        {
            LL x=lower_bound(b+1,b+1+len,a[i]-K)-b;
            LL y=upper_bound(b+1,b+1+len,a[i]+K)-b-1;
            up[i]=y;
            low[i]=x-1;
        }
    
        LL L=1,R=0;
        LL ret=0;
        for(int i=1;i<=M;i++)
        {
    
            while(R<q[i].r)//区间增大
            {
    //            LL x=lower_bound(b+1,b+1+len,a[R+1]-K)-b;
    //            LL y=upper_bound(b+1,b+1+len,a[R+1]+K)-b-1;
                //现在在b数组[x,y]之间的所有的数都是符合条件的
                ret+=Query(up[R+1])-Query(low[R+1]);
                update(sea(a[R+1]),1);//这个必须放在上面的下面 因为如果先放的话本身的值岂不是算进去了
                R++;
            }
            while(R>q[i].r)//区间减小
            {
                update(sea(a[R]),-1);//这个必须放在下面的上面  因为你要减去它的影响 自然也不能算本身-本身
    //            LL x=lower_bound(b+1,b+1+len,a[R]-K)-b;
    //            LL y=upper_bound(b+1,b+1+len,a[R]+K)-b-1;
                ret-=Query(up[R])-Query(low[R]);
                R--;
            }
            while(L<q[i].l)//区间减小
            {
                update(sea(a[L]),-1);
    //            solve(L,-1);
    //            LL x=lower_bound(b+1,b+1+len,a[L]-K)-b;
    //            LL y=upper_bound(b+1,b+1+len,a[L]+K)-b-1;
                ret-=Query(up[L])-Query(low[L]);
                L++;
            }
            while(L>q[i].l)//区间增大
            {
    
    //            LL x=lower_bound(b+1,b+1+len,a[L-1]-K)-b;
    //            LL y=upper_bound(b+1,b+1+len,a[L-1]+K)-b-1;
                ret+=Query(up[L-1])-Query(low[L-1]);
                update(sea(a[L-1]),1);
                L--;
            }
            ans[q[i].num]=ret;
        }
    
        for(int i=1;i<=M;i++) printf("%lld
    ",ans[i]);
            //cout<<ans[i]<<endl;
        return 0;
    }
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    java 使用相对路径读取文件
    appium 使用过程问题踩坑-笔记
    CentOS下启动Tomcat
    jodis遇到的问题
    CentOS 7.0 防火墙
    sentinel
    keepalived
    在Tomat7上使用Redis保存Session
    Log4j 使用
    java路径问题
  • 原文地址:https://www.cnblogs.com/caijiaming/p/10896352.html
Copyright © 2020-2023  润新知