1. 程式人生 > >CSU 1515: Sequence(莫隊演算法)

CSU 1515: Sequence(莫隊演算法)

Description

Give you a sequence consisted of n numbers. You are required to answer how many pairs of numbers (ai, aj) satisfy that | ai - aj | = 1 and L ≤ i < j ≤ R.

Input

The input consists of one or more test cases.
For each case, the first line contains two numbers n and m, which represent the length of the number sequence and the number of queries. ( 1 ≤ n ≤ 10^4, 1 ≤ m ≤ 10^5 )
The second line consists of n numbers separated by n - 1 spaces.( 0 ≤ ai < 2^31 )
Then the m lines followed each contain two values Li and Ri.

Output

For each case just output the answers in m lines.

Sample Input

10 10
5 5 1 3 6 3 5 7 1 7
3 4
6 8
8 9
2 8
5 7
6 7
1 9
3 10
3 10
5 6

Sample Output

0
0
0
3
1
0
4
3
3

0

solution:

莫隊演算法模板題,只需要自己修稿O(1)的部分

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<map>
using namespace std;
const int maxn = 100050;
int unit;
int a[maxn];
int tmp, ans[maxn];
map<int, int>num;
struct Query
{
	int id, l, r;
	bool operator<(const Query &q)const
	{
		if (l / unit == q.l / unit) return r < q.r;
		return l / unit < q.l / unit;
	}
}query[maxn];
void insert(int x)
{
	++num[x];
	tmp += num[x + 1] + num[x - 1];
}
void remove(int x)
{
	--num[x];
	tmp-= (num[x + 1]+num[x - 1]);
}
int main()
{
	int n, m;
	while (~scanf("%d%d", &n, &m))
	{
		for (int i = 1; i <= n; ++i) 
			scanf("%d", &a[i]);
		unit = (int)sqrt((double)n);
		for (int i = 0; i < m; ++i)
		{
			query[i].id = i;
			scanf("%d%d", &query[i].l, &query[i].r);
		}
		sort(query, query + m);
		int l = 1, r = 0;
		tmp = 0;
		num.clear();
		for (int i = 0; i<m; ++i)
		{
			while (l < query[i].l) remove(a[l++]);
			while (l > query[i].l) insert(a[--l]);
			while (r>query[i].r) remove(a[r--]);
			while (r < query[i].r) insert(a[++r]);
			ans[query[i].id] = tmp;
		}
		for (int i = 0; i <m; ++i)
			printf("%d\n", ans[i]);
	}
	return 0;
}