莫队算法 牛客多校赛题

Given a sequence of integers a 1 , a 2 , ..., a n and q pairs of integers (l 1 , r 1 ), (l 2 , r 2 ), ..., (l q , r q ), find count(l 1 , r 1 ),
count(l 2 , r 2 ), ..., count(l q , r q ) where count(i, j) is the number of different integers among a 1 , a 2 , ..., a i , a j , a j + 1 ,
..., a n .
输入描述:
The input consists of several test cases and is terminated by end-of-file.
The first line of each test cases contains two integers n and q.
The second line contains n integers a 1 , a 2 , ..., a n .
The i-th of the following q lines contains two integers l i and r i .
输出描述:
For each test case, print q integers which denote the result.
备注
* 1 ≤ n, q ≤ 10 5
* 1 ≤ a i ≤ n
* 1 ≤ l i , r i ≤ n
* The number of test cases does not exceed 10.
示例1:
输入
3 2
1 2 1
1 2
1 3
4 1
1 2 3 4
1 3
输出
2
1
3

题意:输入N,M ,接下来N 个数,接下来M个询问[L,R],求[1,L]AND[R,N]有几种不重复的数

思路:莫队算法https://blog.csdn.net/y201619819/article/details/81136011

#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
#define LL long long
const LL MAXN = 100005;
struct node {
	LL r, l, id, ans;//id为排序前编号,r、l是输入的要查询数据,ans为结果
}q[MAXN];
LL block;//分成的块数
LL s[MAXN];
LL num[MAXN];//记录出现的额次数
bool cmp1(node a,node b) {//先按左边所在的块数从小到大排,块数相同的按右边界从小到大排序
	if (a.l / block != b.l / block)return a.l < b.l;
	return a.r < b.r;
}
bool cmp2(node a, node b) {//排回原序
	return a.id < b.id;
}
int main() {
	LL n, m;
	while (scanf("%lld %lld", &n, &m) != EOF) {
		LL ans, l, r;
		
		block = sqrt(n);//block=sqrt(MAXN);块数,自己定,玄学
		for (int i = 1; i <= n; i++) {
			scanf("%lld", &s[i]);
		}
		for (int i = 0; i < m; i++) {
			scanf("%lld %lld", &q[i].l, &q[i].r);
			q[i].id = i + 1;
			q[i].ans = 0;
		}

		sort(q, q + m, cmp1);//先按左边所在的块数从小到大排,块数相同的按右边界从小到大排序

		memset(num, 0, sizeof(num));//初始化
		//初始化一个正确的开头,也可以计算第一个数据作为开头
		l = 1;
		r = n;
		num[s[1]]++;
		num[s[n]]++;
		if (s[1] == s[n])ans = 1;
		else ans = 2;
		
		for (int i = 0; i < m; i++) {//暴力,此题为[1,l],[l,n]两个区间,不是[l,r]
			while (l < q[i].l) {
				l++;
				num[s[l]]++;
				if (num[s[l]] == 1)ans++;
			}
			while (l > q[i].l) {
				l--;
				num[s[l + 1]]--;
				if (num[s[l+1]] == 0)ans--;
			}
			while (r < q[i].r) {
				r++;
				num[s[r - 1]]--;
				if (num[s[r - 1]] == 0)ans--;
			}
			while (r > q[i].r) {
				r--;
				num[s[r]]++;
				if (num[s[r]] == 1)ans++;
			}
			q[i].ans = ans;//结果
		}
		sort(q, q + m, cmp2);//排回原序
		for (int i = 0; i < m; i++)
			printf("%lld\n", q[i].ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/y201619819/article/details/81136026