【洛谷】题解 P4113 【[HEOI2012]采花】
程序员文章站
2022-05-09 13:50:25
...
好久没写题解了,有点怀念
因为我最近在练莫队,所以这道题一眼看过就码了个莫队,然后愉快地Tle了。。
看到这道题的数据范围,发现莫队是不行的,看题解发现了一种树状数组的玩法。
然后我一直用pascal捣鼓,结果一直wa得只有10分,实在是找不出问题。
不过我今天突然想到可以用c++搞一搞,结果就真的过了。
思路:
用Next[i]表示与第i朵花颜色相同的下一朵花的位置
发现:一段区间内,从左到右第二次出现的颜色对ans产生贡献,所以可以用树状数组维护前缀和。
那么Next就是用于快速得到某一段区间的第二次出现的颜色
对于查询则是用离线
LuoGu加强数据后最后一个点一直Tle,加了氧气才过掉了,不过原始数据我的程序还是跑的过的,BZOJ里也ac了
但!为防止抄袭,我就不粘AC代码了,粘一个T的吧(具体代码还要自己写哦!!!)
#include <bits/stdc++.h>
using namespace std;
#define res register int
#define maxn 2000010
#define inf 2147483647
struct node {
int l, r, id, ans;
};
node q[maxn];
int Next[maxn], color[maxn], p[maxn], n, m, c, tree[maxn];
inline int read() {
int s = 0, w = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') w = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
s = (s << 3) + (s << 1) + (c ^ 48), c = getchar();
return s * w;
}
inline bool cmp1(node x, node y) {
return x.l == y.l ? x.r < y.r : x.l < y.l;
}
inline bool cmp2(node x, node y) {
return x.id < y.id;
}
inline void add(int x, int y) {
for (; x <= n; x += (x & (-x)))
tree[x] += y;
}
inline int query(int x) {
int sum = 0;
for (; x > 0; x -= (x & (-x)))
sum += tree[x];
return sum;
}
int main() {
n = read(), c = read(), m = read();
for (res i = 1; i <= n; ++i)
color[i] = read();
for (res i = n; i > 0; --i)
Next[i] = p[color[i]], p[color[i]] = i;
for (res i = 1; i <= c; ++i)
if (p[i] && Next[p[i]])
add(Next[p[i]], 1);
for (res i = 1; i <= m; ++i)
q[i].l = read(), q[i].r = read(), q[i].id = i;
sort(q + 1, q + 1 + m, cmp1);
int l = 1;
for (res i = 1; i <= m; ++i) {
for (; l < q[i].l; ++l) {
if (Next[l]) add(Next[l], -1);
if (Next[l] && Next[Next[l]]) add(Next[Next[l]], 1);
}
q[i].ans = query(q[i].r) - query(q[i].l - 1);
}
sort(q + 1, q + 1 + m, cmp2);
for (res i = 1; i <= m; ++i) printf("%d\n", q[i].ans);
return 0;
}