2019湘潭邀请赛C - Chika and Friendly Pairs——莫队+树状数组+离散化

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

题目大意: 给你一个长度为n的序列,有m次查询操作,每次查询[L,R]区间的友好对的个数。

友好对的定义:满足i<j,且|ai-aj|<=K。

题解:首先我们把题意转换一下,相当于枚举[L,R]区间内每个值a[i],且[L,R]区间内值在[ai-k,ai+k]的数的个数。

这时候我们发现这是树状数组一个很经典的用法:求所有值在一段区间的的数的个数(类似于求逆序数的做法)。

但是我们发现值比较大,而树状数组不可能开这么大的空间,但是可以发现数的范围比较小,因此可以考虑离散化。

 最后我们把所有查询离线处理一下,其实也是很经典的莫队做法,考虑一下L,R左移右移时对答案的贡献就行了。

时间复杂度:O(n*sqrt(n)*log(n))

代码实现:

#pragma GCC optimize(2)
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#define PI atan(1.0) * 4
#define E 2.718281828
#define rp(i, s, t) for (register int i = (s); i <= (t); i++)
#define RP(i, t, s) for (register int i = (t); i >= (s); i--)
#define ll long long
#define ull unsigned long long
#define mst(a, b) memset(a, b, sizeof(a))
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define pii pair<int, int>
#define mp make_pair
#define pb push_back
#define debug printf("ac\n");
using namespace std;
inline int read()
{
    int a = 0, b = 1;
    char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-')
            b = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9')
    {
        a = (a << 3) + (a << 1) + c - '0';
        c = getchar();
    }
    return a * b;
}
const int INF = 0x3f3f3f3f;
const int N = 27000+7;
int B[N*3];
int n,m,k;
int a[N];
int L=1,R=0,res[N],ans;
int block,num,belong[N];
struct query{
    int l,r,id;
}q[N];
bool cmp(const query& a,const query& b){
    return (belong[a.l]^belong[b.l])?belong[a.l]<belong[b.l]:((belong[a.l]&1)?a.r<b.r:a.r>b.r);
}
inline lowbit(int x){return x&(-x);}
inline int query(int index){
    int res=0;
    for(int i=index;i>=1;i-=lowbit(i)) res+=B[i];
    return res;
}
inline void update(int index,int val){
    for(int i=index;i<=N*3-7;i+=lowbit(i)) B[i]+=val; 
}
vector<int> v;
int up[N],down[N],cur[N];
inline void add(int pos){
    ans+=query(up[pos])-query(down[pos]-1);
    update(cur[pos],1);
}
inline void del(int pos){
    update(cur[pos],-1);
    ans-=query(up[pos])-query(down[pos]-1);
}
int main()
{
    n=read(),m=read(),k=read();
    rp(i,1,n) a[i]=read(),v.pb(a[i]),v.pb(a[i]-k),v.pb(a[i]+k);
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    block=sqrt(n);
    num=n/block;if(n%block) num++;
    rp(i,1,n) belong[i]=(i-1)/block+1;
    rp(i,1,m) q[i].l=read(),q[i].r=read(),q[i].id=i;
    sort(q+1,q+1+m,cmp);
    rp(i,1,n){
        up[i]=lower_bound(v.begin(),v.end(),a[i]+k)-v.begin()+1;
        down[i]=lower_bound(v.begin(),v.end(),a[i]-k)-v.begin()+1;
        cur[i]=lower_bound(v.begin(),v.end(),a[i])-v.begin()+1;
    }
    rp(i,1,m){
        int ql=q[i].l,qr=q[i].r;
        while(L<ql) del(L++);
        while(ql<L) add(--L);
        while(R<qr) add(++R);
        while(qr<R) del(R--);
        res[q[i].id]=ans;
    }
    rp(i,1,m) printf("%d\n",res[i]);
    return 0;
}
发布了342 篇原创文章 · 获赞 220 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_43472263/article/details/104911109