洛谷4113(树状数组+离线处理)

[HEOI2012]采花

题目描述

萧薰儿是古国的公主,平时的一大爱好是采花。

今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花。

花园足够大,容纳了 n 朵花,共有 c 种颜色,用整数 1 ~ c 表示。且花是排成一排的,以便于公主采花。公主每次采花后会统计采到的花的颜色数,颜色数越多她会越高兴。同时,她有一癖好,她不允许最后自己采到的花中,某一颜色的花只有一朵。为此,公主每采一朵花,要么此前已采到此颜色的花,要么有相当正确的直觉告诉她,她必能再次采到此颜色的花。

由于时间关系,公主只能走过花园连续的一段进行采花,便让女仆福涵洁安排行程。福涵洁综合各种因素拟定了 m 个行程,然后一一向你询问公主能采到的花共有几种不同的颜色。

输入格式

输入的第一行是三个用空格隔开的整数,分别代表花的个数 n,花的颜色数 c,以及行程数 m

输入的第二行是 n 个用空格隔开的整数,第 i 个整数代表第 i 朵花的颜色 xi

3 行到第 (m + 2) 行,每行两个整数 l, r,第 (i + 2) 行的数字代表第 i 次行程为第 l 到第 r 朵花。

输出格式

共输出 m 行,每行一个整数。第 i 行的整数代表第 i 次行程公主能采到的花共有几种不同的颜色。

样例 #1

样例输入 #1

5 3 5
1 2 2 3 1
1 5
1 2
2 2
2 3
3 5

样例输出 #1

2
0
0
1
0

提示

输入输出样例 1 解释

共有五朵花,颜色分别为 1,2,2,3,1

对于第一次行程,公主采花的区间为 [1, 5],可以采位置 1,2,3,5 处的花,共有 1 和 2 两种不同的颜色。

对于第二次行程,公主采花的区间为 [1, 2],但是颜色为 1 和 2 的花都只出现了一次,因此公主无花可采。

对于第三次行程,公主采花的区间为 [2, 2],但是颜色为 2 的花只出现了一次,公主无花可采。

对于第四次行程,公主采花的区间为 [2, 3],可以采 2,3 位置的花,只有 2 这一种颜色。

对于第五次行程,公主采花的区间为 [3,5],但是颜色为 1, 2, 3 的花都只出现了一次,因此公主无花可采。

思路:离线处理,在将询问按照左端点从大到小排序,处理每个询问。

思路类似于:hdu-4630(树状数组) - 魏老6 - 博客园 (cnblogs.com)

但多了一步删除操作。

代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include<algorithm>
#include<fstream>
#include<iostream>
#include<cstdio>
#include<deque>
#include<string>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<unordered_map>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 310000
#define N 5000000
#define M (int)1e8-3
#define endl '\n'
#define exp 1e-8
#define lc p << 1
#define rc p << 1|1
#define lowbit(x) ((x)&-(x))
const double pi = acos(-1.0);
typedef long long LL;
typedef unsigned long long ULL;
inline ULL read() {
	ULL x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch>'9') {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = (x << 1) + (x << 3) + (ch ^ 48);
		ch = getchar();
	}
	return x * f;
}
void print(ULL x) {
	if (x > 9)print(x / 10);
	putchar(x % 10 ^ 48);
}
int n, m, arr[N], tree[N],ans[N],k,last[N],old[N];
struct node
{
	int l, r, i;
	bool operator < (const node& a)const
	{
		return l > a.l;
	}
}qu[N];
void update(int x, int d)
{
	while (x <= N)
	{
		tree[x] += d;
		x += lowbit(x);
	}
}
int sum(int x)
{
	int res = 0;
	while (x)
	{
		res += tree[x];
		x -= lowbit(x);
	}
	return res;
}
int main()
{
	n = read(), k = read(), m = read();
	for (int i = 1; i <= n; i++)
	{
		arr[i] = read();
	}
	for (int i = 1; i <= m; i++)
	{
		qu[i].l = read(), qu[i].r = read(), qu[i].i = i;
	}
	sort(qu + 1, qu + 1 + m);
	int j = 1;
	for (int i = n; i >= 1; i--)
	{
		if (last[arr[i]])
		{
			update(last[arr[i]], 1);
			if (old[arr[i]])
			{
				update(old[arr[i]], -1);
			}
			old[arr[i]] = last[arr[i]];
		}
		last[arr[i]] = i;
		while (qu[j].l >= i)
		{
			ans[qu[j].i] = sum(qu[j].r) - sum(qu[j].l - 1);
			j++;
			if (j > m)break;
		}
	}
	for (int i = 1; i <= m; i++)
	{
		printf("%d\n", ans[i]);
	}
	return 0;
}
posted @ 2023-04-04 21:40  魏老6  阅读(32)  评论(0编辑  收藏  举报