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