莫队板子

Chika and Friendly Pairs

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 ai−aj 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 L≤i<j≤R.

    Input
    The first line contains 3 integers n (1≤n≤27000), m (1≤m≤27000) and K (1≤K≤109), 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 L, R (1≤L≤R≤n). 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.
题意:
求任意区间里面(a[i]-a[j])<k有多少对n个数,m次询问。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#define lowbits(x) x&(-x)
using namespace std;
const int N=3e4;
int sr[N],sl[N],sm[N],num[N],tr[N],cnt=0,k,sum[N],pox[N];
struct node{                                //树状数组维护每一个莫队块中序列个数,前缀数组的作用;
    int l,r,id,pot;
    bool operator <(node a)const               //预置排序;
    {
        return pot==a.pot?(pot&1?r<a.r:r>a.r):pot<a.pot;
    }
}mp[N];
inline int read()                //快读;
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
void update(int x, int val)             //添加元素;
{
    if(!x) return ;
    while(x<N){
        tr[x]+=val;
        x+=lowbits(x);
    }
}
int query(int x)             //查询;
{
    int ans=0;
    while(x>0){
        ans+=tr[x];
        x-=lowbits(x);
    }
    return ans;
}
void add(int x)                  //上传数据,计算(num-k,num+k)的数据个数;
{
    cnt+=(query(sr[x])-query(sl[x]));
    update(sm[x],1);
}
void del(int x)                //删除元素+减去个数;
{
    update(sm[x],-1);
    cnt-=(query(sr[x])-query(sl[x]));
}
int main()
{
    int n,m,tot=1;
    register int i;              //加速运行,防止卡常;
    //scanf("%d%d%d",&n,&m,&k);
    n=read(),m=read(),k=read();
    int block=(int)sqrt(n);            //莫队分块,用于对输入排序;
    for(i=1;i<=n;++i)
        num[i]=read(),pox[i]=num[i];
    for(i=0;i<m;++i){
        mp[i].l=read();
        mp[i].r=read();
        mp[i].pot=mp[i].l/block;
        mp[i].id=i;
    }
    sort(pox+1,pox+n+1);
    sort(mp,mp+m);
    for(i=2;i<=n;++i)                  //对数据离散化;
        if(pox[i]!=pox[i-1]) pox[++tot]=pox[i];
    for(i=1;i<=n;++i){
        sl[i]=lower_bound(pox+1,pox+tot+1,num[i]-k)-pox-1;  //取每一个数据的上下区间,方便后面的数据处理;
        sr[i]=upper_bound(pox+1,pox+tot+1,num[i]+k)-pox-1;
        sm[i]=lower_bound(pox+1,pox+tot+1,num[i])-pox;
    }
    int l=1,r=0;
    for(i=0;i<m;++i){
        while(r<mp[i].r) add(++r); 
        while(r>mp[i].r) del(r--);
        while(l<mp[i].l) del(l++);
        while(l>mp[i].l) add(--l);
       sum[mp[i].id]=cnt;               //记录结果;
    }
    for(i=0;i<m;++i){
        printf("%d\n",sum[i]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值