2019CCPC湘潭邀请赛 Chika and Friendly Pairs(莫队+树状数组)

2024-04-16 01:18

本文主要是介绍2019CCPC湘潭邀请赛 Chika and Friendly Pairs(莫队+树状数组),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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湖南全国邀请赛(广东省赛、江苏省赛)重现赛

题意: 询问某个区间内差值不大于k的数对数目。
思路:
莫队算法就是双指针加排序,通过分块,按块排序,块内排右指针。
由此在块的内部相邻左端点变化最大为 n \sqrt n n ,而右端点是单调的,可以不计。
那么m次询问均摊下来最大 m n m\sqrt n mn ,观察n和m的范围,越为3e4,莫队可行!

我们用双指针维护到当前询问区间,区间变化对答案的影响可以用树状数组记录。
这类似与逆序对,你求与x差距不大于k的数,就是 s u m ( x + k ) − s u m ( x − k − 1 ) sum(x + k) - sum(x - k - 1) sum(x+k)sum(xk1)
当然,数字很大,再离散化一遍就好了。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>using namespace std;const int maxn = 1e5 + 7;struct Query {int l,r,id;
}q[maxn];int a[maxn];
int t[maxn],tot,cnt,sqr;
int L,R,num,ans[maxn];
int mp[maxn][2];
int c[maxn];void init() {sort(t + 1,t + 1 + tot);cnt = unique(t + 1,t + 1 + tot) - t - 1;
}int Find(int x) {return lower_bound(t + 1,t + 1 + cnt,x) - t;
}int cmp(Query a,Query b) {return a.l / sqr == b.l / sqr ? a.r < b.r : a.l < b.l;
}void add(int x,int v) {while(x < maxn) {c[x] += v;x += x & (-x);}
}int sum(int x) {int res = 0;while(x) {res += c[x];x -= x & (-x);}return res;
}void Add(int x) {num += sum(mp[a[x]][1]) - sum(mp[a[x]][0]);add(a[x],1);
}void Del(int x) {add(a[x],-1);num -= sum(mp[a[x]][1]) - sum(mp[a[x]][0]);
}int main() {int n,m,k;scanf("%d%d%d",&n,&m,&k);for(int i = 1;i <= n;i++) {scanf("%d",&a[i]);t[++tot] = a[i];t[++tot] = a[i] - k - 1;t[++tot] = a[i] + k;}init();for(int i = 1;i <= m;i++) {scanf("%d%d",&q[i].l,&q[i].r);q[i].id = i;}for(int i = 1;i <= n;i++) {int now = Find(a[i]);mp[now][0] = Find(a[i] - k - 1);mp[now][1] = Find(a[i] + k);a[i] = now;}sqr = sqrt(n);sort(q + 1,q + 1 + m,cmp);L = 1,R = 0;for(int i = 1;i <= m;i++) {int l = q[i].l,r = q[i].r;int id = q[i].id;while(L < l) {Del(L++);}while(L > l) {Add(--L);}while(R < r) {Add(++R);}while(R > r) {Del(R--);}ans[id] = num;}for(int i = 1;i <= m;i++) {printf("%d\n",ans[i]);}return 0;
}

这篇关于2019CCPC湘潭邀请赛 Chika and Friendly Pairs(莫队+树状数组)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/907434

相关文章

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

leetcode-24Swap Nodes in Pairs

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode swapPairs(L

C语言:柔性数组

数组定义 柔性数组 err int arr[0] = {0}; // ERROR 柔性数组 // 常见struct Test{int len;char arr[1024];} // 柔性数组struct Test{int len;char arr[0];}struct Test *t;t = malloc(sizeof(Test) + 11);strcpy(t->arr,

C 语言基础之数组

文章目录 什么是数组数组变量的声明多维数组 什么是数组 数组,顾名思义,就是一组数。 假如班上有 30 个同学,让你编程统计每个人的分数,求最高分、最低分、平均分等。如果不知道数组,你只能这样写代码: int ZhangSan_score = 95;int LiSi_score = 90;......int LiuDong_score = 100;int Zhou

计算数组的斜率,偏移,R2

模拟Excel中的R2的计算。         public bool fnCheckRear_R2(List<double[]> lRear, int iMinRear, int iMaxRear, ref double dR2)         {             bool bResult = true;             int n = 0;             dou

C# double[] 和Matlab数组MWArray[]转换

C# double[] 转换成MWArray[], 直接赋值就行             MWNumericArray[] ma = new MWNumericArray[4];             double[] dT = new double[] { 0 };             double[] dT1 = new double[] { 0,2 };

PHP7扩展开发之数组处理

前言 这次,我们将演示如何在PHP扩展中如何对数组进行处理。要实现的PHP代码如下: <?phpfunction array_concat ($arr, $prefix) {foreach($arr as $key => $val) {if (isset($prefix[$key]) && is_string($val) && is_string($prefix[$key])) {$arr[

Go 数组赋值问题

package mainimport "fmt"type Student struct {Name stringAge int}func main() {data := make(map[string]*Student)list := []Student{{Name:"a",Age:1},{Name:"b",Age:2},{Name:"c",Age:3},}// 错误 都指向了最后一个v// a

码蹄集部分题目(2024OJ赛9.4-9.8;线段树+树状数组)

1🐋🐋配对最小值(王者;树状数组) 时间限制:1秒 占用内存:64M 🐟题目思路 MT3065 配对最小值_哔哩哔哩_bilibili 🐟代码 #include<bits/stdc++.h> using namespace std;const int N=1e5+7;int a[N],b[N],c[N],n,q;struct QUERY{int l,r,id;}que