散落星河的记忆🌠
Published on 2017-09-02 11:31 in 暂未分类 with 散落星河的记忆🌠

[BZOJ 2743] [HEOI 2012] 采花

Description

萧芸斓是Z国的公主,平时的一大爱好是采花。今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花。花园足够大,容纳了 \(n\) 朵花,花有 \(c\) 种颜色(用整数 \(1-c\) 表示),且花是排成一排的,以便于公主采花。公主每次采花后会统计采到的花的颜色数,颜色数越多她会越高兴!同时,她有一癖好,她不允许最后自己采到的花中,某一颜色的花只有一朵。为此,公主每采一朵花,要么此前已采到此颜色的花,要么有相当正确的直觉告诉她,她必能再次采到此颜色的花。由于时间关系,公主只能走过花园连续的一段进行采花,便让女仆福涵洁安排行程。福涵洁综合各种因素拟定了 \(m\) 个行程,然后一一向你询问公主能采到多少朵花(她知道你是编程高手,定能快速给出答案!),最后会选择令公主最高兴的行程(为了拿到更多奖金!)。

Input

第一行四个空格隔开的整数 \(n,c\) 以及 \(m\)

接下来一行 \(n\) 个空格隔开的整数,每个数在 \([1, c]\) 间,第 \(i\) 个数表示第 \(i\) 朵花的颜色。

接下来 \(m\) 行每行两个空格隔开的整数 \(l\)\(r\) \((l ≤ r)\),表示女仆安排的行程为公主经过第 \(l\) 到第 \(r\) 朵花进行采花。

Output

\(m\) 行,每行一个整数,第 \(i\) 个数表示公主在女仆的第 \(i\) 个行程中能采到的花的颜色数。

Sample Input

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

Sample Output

2 
0 
0 
1 
0 

HINT

\(1 ≤ n ≤ 10^6,c ≤ n,m ≤10^6\)

Solution

HH的项链加强版。将询问按照左端点排序,设 \(nxt[i]\) 表示下一个与 \(i\) 颜色相同的点的位置。

当扫过点 \(i\) 后,HH的项链是 update(i, -1), update(nxt[i], 1),这里改成 update(nxt[i], -1), update(nxt[nxt[i]], 1) 就好。

Code

#include <cstdio>
#include <algorithm>

const int N = 1000005;
struct Node {
	int l, r, id;
	bool operator < (const Node &rhs) const {
		return l < rhs.l;
	}
} b[N];
int nxt[N], pos[N], sum[N], ans[N], a[N], n, c, m;

int read() {
	int x = 0; char c = getchar();
	while (c < '0' || c > '9') c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
	return x;
}
void update(int x, int y) {
	while (x <= n) sum[x] += y, x += x & (-x);
}
int query(int x) {
	int res = 0;
	while (x) res += sum[x], x -= x & (-x);
	return res;
}
int main() {
	n = read(), c = read(), m = read();
	for (int i = 1; i <= n; ++i) a[i] = read();
	for (int i = n; i; --i) {
		if (pos[a[i]]) nxt[i] = pos[a[i]];
		pos[a[i]] = i;
	}
	for (int i = 1; i <= m; ++i) b[i].l = read(), b[i].r = read(), b[i].id = i;
	std::sort(b + 1, b + m + 1);
	for (int i = 1; i <= c; ++i) if (nxt[pos[i]]) update(nxt[pos[i]], 1);
	for (int i = 1, j = 1; i <= n; ++i) {
		while (b[j].l == i) ans[b[j].id] = query(b[j].r), ++j;
		if (nxt[i]) {
			update(nxt[i], -1);
			if (nxt[nxt[i]]) update(nxt[nxt[i]], 1);
		}
	}
	for (int i = 1; i <= m; ++i) printf("%d\n", ans[i]);
	return 0;
}
posted @ 2019-02-12 19:43  散落星河的记忆🌠  阅读(138)  评论(0编辑  收藏  举报