题解 CF220B 【Little Elephant and Array】

Warriors_Cat

2020-12-04 09:40:38

Solution

似乎莫队的思路更好想一些? --- ### $Solution:$ 首先,$a_i> n$ 的 $a_i$ 肯定没有贡献,因为一共就只有 $n$ 个数。所以 $a_i > n$ 的都可以直接舍掉,这样子值域就也是 $10^5$ 了,无需离散化。 由于在此题是要恰好为 $a_i$ 次,所以 `Insert` 和 `Delete` 也要注意,一旦不是 $a_i$ 就要把贡献 $-1$。 比如说,在 `Insert` 的时候,当 `cnt[a[x]] == a[x] + 1` 时,贡献要减回来。`Delete` 也同理。 后面就是莫队基础操作了,时间复杂度为 $O(m\log m+n\sqrt{n})$。 --- ### $Code:$ ```cpp #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> #include <vector> #include <cmath> using namespace std; #define ll long long #define fi first #define se second #define x1 x_csyakioi_1 #define x2 x_csyakioi_2 #define y1 y_csyakioi_1 #define y2 y_csyakioi_2 #define y0 y_csyakioi_0 #define dingyi int mid = l + r >> 1, ls = p << 1, rs = p << 1 | 1; inline int read(){ int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ x = x * 10 + (ch ^ 48); ch = getchar(); } return x * f; } const int N = 100010; int n, m, k, a[N], pos[N], cnt[N], ans[N], res; struct ask{ int l, r, idx; bool operator < (const ask&rhs)const{ return pos[l] ^ pos[rhs.l] ? l < rhs.l : pos[l] & 1 ? r < rhs.r : r > rhs.r; } }q[N]; inline void Insert(int x){ if(a[x] > n) return; ++cnt[a[x]]; if(cnt[a[x]] == a[x]) ++res; if(cnt[a[x]] == a[x] + 1) --res; } inline void Delete(int x){ if(a[x] > n) return; if(cnt[a[x]] == a[x] + 1) ++res; if(cnt[a[x]] == a[x]) --res; --cnt[a[x]]; } int main(){ n = read(); m = read(); k = sqrt(n); for(int i = 1; i <= n; ++i) a[i] = read(); for(int i = 1; i <= n; ++i) pos[i] = (i - 1) / k + 1; for(int i = 1; i <= m; ++i) q[i].l = read(), q[i].r = read(), q[i].idx = i; sort(q + 1, q + m + 1); int L = 1, R = 0; for(int i = 1; i <= m; ++i){ int x = q[i].l, y = q[i].r, idx = q[i].idx; while(R < y) Insert(++R); while(L > x) Insert(--L); while(R > y) Delete(R--); while(L < x) Delete(L++); ans[idx] = res; } for(int i = 1; i <= m; ++i) printf("%d\n", ans[i]); return 0; } ```