码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2019-05-20 21:22:40      阅读:467      评论:0      收藏:0      [点我收藏+]

标签:tar   contain   code   hdu   print   复杂度   including   ref   several   

题目链接: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\n",ans[i]);
        //cout<<ans[i]<<endl;
    return 0;
}

 

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

标签:tar   contain   code   hdu   print   复杂度   including   ref   several   

原文地址:https://www.cnblogs.com/caijiaming/p/10896352.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!