洛谷P4113 [HEOI2012]采花

(large{题目链接})
(\)
(Large extbf{Solution: } large{HH的项链升级版,不过做法差不多。\设vis_i表示数组中与i颜色相同的前一朵花的位置,我是把询问按右边界排的序,那么问题来了,\如果一朵花满足 vis[i]真并且vis[vis[i]]真,如果在i位置上加的话,查询时,可能会多加,因为前面那朵花不一定在l右边。\所以我们在vis[i]上加,就可以维护答案了。})
(\)
(Large extbf{Code: })

#include <bits/stdc++.h>
using namespace std;

const int N = 2e6 + 5;

int n, t[N], vis[N], s[N], ans[N], pos[N];

struct Qus {
	int pos, l, r;
}p[N];

int read() {
	char ch = getchar();
	int x = 0;
	while (!isdigit(ch)) ch = getchar();
	while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
	return x;
}

int lowbit(int x) { return x & (-x); }

bool cmp(Qus a, Qus b) { return a.r < b.r; }

void add(int x, int k) { for (; x <= n; s[x] += k, x += lowbit(x)); }

int sum(int x) { int ret = 0; for (; x ; ret += s[x], x -= lowbit(x)); return ret; }

int main() {
	int m, c;
	n = read(), c = read(), m = read();
	for (int i = 1; i <= n; ++i) t[i] = read();
	for (int i = 1; i <= m; ++i) p[i].l = read(), p[i].r = read(), p[i].pos = i;
	sort(p + 1, p + 1 + m, cmp);
	for (int i = 1; i <= n; ++i) vis[i] = pos[t[i]], pos[t[i]] = i;
	int nxt = 1;
	for (int i = 1; i <= m; ++i) {
		for (int j = nxt; j <= p[i].r; ++j) {
			if (vis[j]) add(vis[j], 1);
			if (vis[j] && vis[vis[j]]) add(vis[vis[j]], -1);
		}
		nxt = p[i].r + 1;
		ans[p[i].pos] = sum(p[i].r) - sum(p[i].l - 1);
	}
	for (int i = 1; i <= m; ++i) printf("%d
", ans[i]);
	return 0;
}
原文地址:https://www.cnblogs.com/Miraclys/p/12658089.html