洛谷P2056 采药
-
- 52通过
- 99提交
- 题目提供者shengmingkexue
- 标签云端↑
- 难度省选/NOI-
- 时空限制1s / 128MB
讨论 题解
最新讨论更多讨论
- 求助莫队为什么被卡
- ??
题目描述
萧芸斓是 Z国的公主,平时的一大爱好是采花。
今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花。花园足够大,容纳了 n 朵花,花有 c 种颜色(用整数 1-c 表示) ,且花是排成一排的,以便于公主采花。
公主每次采花后会统计采到的花的颜色数, 颜色数越多她会越高兴! 同时, 她有一癖好,她不允许最后自己采到的花中,某一颜色的花只有一朵。为此,公主每采一朵花,要么此前已采到此颜色的花,要么有相当正确的直觉告诉她,她必能再次采到此颜色的花。 由于时间关系,公主只能走过花园连续的一段进行采花,便让女仆福涵洁安排行程。福涵洁综合各种因素拟定了 m 个行程,然后一一向你询问公主能采到多少朵花(她知道你是编程高手,定能快速给出答案! ) ,最后会选择令公主最高兴的行程(为了拿到更多奖金! ) 。
输入输出格式
输入格式:
第一行四个空格隔开的整数 n、c 以及 m。
接下来一行 n 个空格隔开的整数,每个数在[1, c]间,第i 个数表示第 i 朵花的颜色。
接下来 m 行每行两个空格隔开的整数 l 和 r(l ≤ r) ,表示女仆安排的行程为公主经过第 l 到第r 朵花进行采花。
输出格式:
共m行, 每行一个整数, 第i个数表示公主在女仆的第i个行程中能采到的花的颜色数。
输入输出样例
输入样例#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
说明
对于100%的数据,1 ≤ n ≤10^5,c ≤ n,m ≤ 10^5。
分析:这道题是bzoj上的阉割版,数据大小是1/10,那么我们完全可以用莫队算法来做!莫队算法的实质还是暴力,不过就是用了一种很奇怪的排序方式233,理解了暴力基本上就理解了莫队算法,在这里不多解释.至于bzoj上的那道题,要用和HH的项链一样的方法:树状数组来解.
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> using namespace std; int n, c, m,a[100010],cnt[100010],ans,anss[100010]; int sizee; struct node { int l, r, id; }e[100010]; bool cmp(node a, node b) { if (a.l / sizee == b.l / sizee) return a.r < b.r; return a.l < b.l; } void add(int x) { if (++cnt[a[x]] == 2) ++ans; } void remove(int x) { if (--cnt[a[x]] == 1) --ans; } int main() { scanf("%d%d%d", &n, &c, &m); sizee = sqrt(n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); for (int i = 1; i <= m; i++) { scanf("%d%d", &e[i].l, &e[i].r); e[i].id = i; } sort(e + 1, e + 1 + m, cmp); int ll = 1, rr = 0; for (int i = 1; i <= m; i++) { int L = e[i].l, R = e[i].r; while (ll < L) remove(ll++); while (ll > L) add(--ll); while (rr < R) add(++rr); while (rr > R) remove(rr--); anss[e[i].id] = ans; } for (int i = 1; i <= m; i++) printf("%d\n", anss[i]); return 0; }