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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM