欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【洛谷】题解 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; 
}
相关标签: 洛谷