JSCPC Chika and Friendly Pairs(莫队+树状数组+离散化)

Chika and Friendly Pairs

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


 

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


 

5 5 3
2 5 7 1 3
6 6
1 3
2 4
1 5
2 3
*/

 

 

Sample Output


 

0

2

1

3

1

题意:给你一个序列,多次询问,每次让你回答一个区间中差的绝对值不超过一个给定常数K的元素对数。

对序列中的所有元素以及这些元素+K,-K后的值进行离散化。 然后使用莫队算法,在莫队算法的端点移动过程中,新加入一个元素x的过程中,将其插入树状数组,查询[x-K,x+K]范围的元素数即可。删除一个元素的过程与其类似。

/**/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>

typedef long long LL;
using namespace std;

const int maxn = 57005;

int n, m, be[maxn], ans[maxn], c[maxn];
LL k, a[maxn], b[maxn], l[maxn], r[maxn];

struct node
{
    int l, r, id;
}q[maxn];

int cmp(node a, node b){
    return (be[a.l] ^ be[b.l]) ? be[a.l] < be[b.l] : ((be[a.l] & 1) ? a.r < b.r : a.r > b.r);
}

int lowbit(int x){
    return x & (-x);
}

void add(int x, int num){
    if(!x) return ;
    while(x <= n){
        c[x] += num;
        x += lowbit(x);
    }
}

int sum(int x){
    int res = 0;
    if(x <= 0) return 0;
    while(x){
        res += c[x];
        x -= lowbit(x);
    }
    return res;
}

int main()
{
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);

    scanf("%d %d %lld", &n, &m, &k);
    int size = sqrt(n);
    int bnum = ceil((double)n / size);
    for (int i = 1; i <= bnum; i++){
        for (int j = (i - 1) * size + 1; j <= i * size; j++) be[j] = i;
    }
    for (int i = 1; i <= n; i++) scanf("%lld", &a[i]), b[i - 1] = a[i];
    for (int i = 1; i <= m; i++){
        scanf("%d %d", &q[i].l, &q[i].r);
        q[i].id = i;
    }
    sort(q + 1, q + 1 + m, cmp);
    sort(b, b + n);
    int pos = unique(b, b + n) - b;
    for (int i = 1; i <= n; i++){
        l[i] = lower_bound(b, b + pos, a[i] - k) - b + 1;
        r[i] = upper_bound(b, b + pos, a[i] + k) - b;
        a[i] = lower_bound(b, b + pos, a[i]) - b + 1;
    }
    int L = 1, R = 0, temp = 0;
    for (int i = 1; i <= m; i++){
        int ql = q[i].l, qr = q[i].r;
        while(L < ql){
            add(a[L], -1);
            temp -= sum(r[L]) - sum(l[L] - 1);
            L++;
        }
        while(L > ql){
            L--;
            temp += sum(r[L]) - sum(l[L] - 1);
            add(a[L], 1);
        }
        while(R < qr){
            R++;
            temp += sum(r[R]) - sum(l[R] - 1);
            add(a[R], 1);
        }
        while(R > qr){
            add(a[R], -1);
            temp -= sum(r[R]) - sum(l[R] - 1);
            R--;
        }
        ans[q[i].id] = temp;

    }
    for (int i = 1; i <= m; i++) printf("%d\n", ans[i]);

    return 0;
}
/**/

/*
5 5 3
2 5 7 1 3
6 6
1 3
2 4
1 5
2 3
*/

 

全部评论

相关推荐

11-26 22:34
已编辑
重庆邮电大学 Java
快手 客户端开发 (n+5)k*16 公积金12
牛客895077908号:佬 什么双非硕啊
点赞 评论 收藏
分享
11-01 08:48
门头沟学院 C++
伤心的候选人在吵架:佬你不要的,能不能拿户口本证明过户给我。。球球了
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务