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 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.

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

2019CCPC湖南全国邀请赛(广东省赛、江苏省赛)重现赛

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;
}

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

时间: 2024-10-10 03:25:11

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

51nod 1290 Counting Diff Pairs | 莫队 树状数组

51nod 1290 Counting Diff Pairs | 莫队 树状数组 题面 一个长度为N的正整数数组A,给出一个数K以及Q个查询,每个查询包含2个数l和r,对于每个查询输出从A[i]到A[j]中,有多少对数,abs(A[i] - A[j]) <= K(abs表示绝对值). 题解 莫队!//其实我就是搜索"51nod + 莫队"找到的这道题-- 七级算法题! 一道320分! 你值得拥有! 题解就是--用个普通的莫队,加上树状数组来统计符合条件的数个数,就好啦. 当增加/

BZOJ3289[JZYZOJP2018]: Mato的文件管理 莫队+树状数组+离散化

        描述 Description     Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号.为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问.Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料.Mato有一个习惯,他总是从文件大小从小到大看资料.他先把要看的文件按编号顺序依次拷贝出来,再用他写的排序程序给文件大小排序.排序程序可以在1单位时间内交换2个相邻的文件(因为加密需要,不能

bzoj 3289: Mato的文件管理 莫队+树状数组

3289: Mato的文件管理 Time Limit: 40 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号.为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问.Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料.Mato有一个习惯,他总是从文件大小从小到大看资料.他先

HihoCoder 1488 : 排队接水(莫队+树状数组)

描述 有n个小朋友需要接水,其中第i个小朋友接水需要ai分钟. 由于水龙头有限,小Hi需要知道如果为第l个到第r个小朋友分配一个水龙头,如何安排他们的接水顺序才能使得他们等待加接水的时间总和最小. 小Hi总共会有m次询问,你能帮助他解决这个问题吗? 假设3个小朋友接水的时间分别是2,3,4.如果他们依次接水,第一位小朋友等待加接水的时间是2,第二位小朋友是5,第三位小朋友是9.时间总和是16. 输入 第一行一个数T(T<=10),表示数据组数 对于每一组数据: 第一行两个数n,m(1<=n,m

BZOJ 3289 Mato的文件管理(莫队+树状数组)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3289 [题目大意] 求静态区间逆序对. [题解] 我们对查询进行莫队操作,对于区间的删改我们可以计算出改变量对于逆序对的贡献, 利用树状数组维护即可. [代码] #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> const int N=50100;

Codeforces 375D Tree and Queries(DFS序+莫队+树状数组)

题目链接  Tree and Queries 题目大意  给出一棵树和每个节点的颜色.每次询问vj, kj 你需要回答在以vj为根的子树中满足条件的的颜色数目, 条件:具有该颜色的节点数量至少为kj. (莫队居然可以过) 首先转DFS序,这样就变成了区间查询. 然后直接套用莫队,求出每次询问状态下的t[],t[k]表示当前区间内拥有k个节点的颜色数量. 然后统计t[k] + t[k + 1], ..., t[MAX]即可,这个过程用树状数组维护. #include <bits/stdc++.h>

BZOJ_3289_Mato的文件管理_莫队+树状数组

Description Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号 .为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问.Mato每天随机选一个区间[l,r ],他今天就看编号在此区间内的这些资料.Mato有一个习惯,他总是从文件大小从小到大看资料.他先把要看的 文件按编号顺序依次拷贝出来,再用他写的排序程序给文件大小排序.排序程序可以在1单位时间内交换2个相邻的 文件(因为加密需要,不能随机访问).Mato想

3289. Mato的文件管理【莫队+树状数组】

Description Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号 .为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问.Mato每天随机选一个区间[l,r ],他今天就看编号在此区间内的这些资料.Mato有一个习惯,他总是从文件大小从小到大看资料.他先把要看的 文件按编号顺序依次拷贝出来,再用他写的排序程序给文件大小排序.排序程序可以在1单位时间内交换2个相邻的 文件(因为加密需要,不能随机访问).Mato想

HH的项链 HYSBZ - 1878 (莫队/ 树状数组)

HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一 段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此他的项链变得越来越长.有一天,他突然提出了一 个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答...因为项链实在是太长了.于是,他只 好求助睿智的你,来解决这个问题. Input 第一行:一个整数N,表示项链的长度. 第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数). 第三行:一个整数