[Byte OI] CSP-S 模擬賽題解
阿新 • • 發佈:2022-03-25
[Byte OI] 佳餚
這道題的部分分只要先離散化,然後暴力就行了。
可能有一些同學是會莫隊的,這道題用莫隊做其實挺簡單的,但莫隊是離線演算法(於是我加了一個強制線上)。
其實一般的莫隊都是可以強制線上化改造成分塊的。
而且這道題的空間給了 \(512 MB\),這就說明我們可以自由的定義陣列,用空間換時間。
首先我們將數列分塊。
我們設 \(F_{i,j}\) 為從第 \(i\) 個塊到第 \(j\) 個塊的答案。
設 \(sum_{i,x}\) 為前 \(i\) 個塊中數字 \(x\) 的出現的總次數。
對於每一個查詢 \(l \sim r\):
如果 \(l\) 和 \(r\) 在一個塊內,暴力列舉即可,時間複雜度 \(\Theta(n)\)
如果 \(l\) 和 \(r\) 在不同的塊內,則我們可以用 \(F\) 陣列得出 \(l \sim r\) 之間整塊的答案,時間複雜度 \(\Theta(n)\)。
接著考慮統計旁邊零散塊的答案,
我們可以用 \(sum\) 陣列得出零散塊中每一個數字的出現次數,
於是我們暴力統計即可。
總時間複雜度 \(\Theta(m \sqrt{n})\),空間複雜度 \(\Theta(n \sqrt{n})\)。
CODE TIME
#include <bits/stdc++.h> using namespace std; int n, m, a[300010], d[300010], siz, bnum, lastans = 0; int F[550][550], cnt[300010], sum[550][300010], L[550], R[550], belong[300010]; inline int price(int x) { if (x < 2) return 0; else if (x == 2) return 1; else return -1; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> m; for (int i = 1; i <= n; i++) cin >> a[i], d[i] = a[i]; sort(d + 1, d + n + 1); int M = unique(d + 1, d + n + 1) - d - 1; for (int i = 1; i <= n; i++) a[i] = lower_bound(d + 1, d + M + 1, a[i]) - d; siz = sqrt(n); bnum = (n - 1) / siz + 1; for (int i = 1; i <= bnum; i++) { L[i] = (i - 1) * siz + 1; R[i] = min(i * siz, n); for (int j = 1; j <= M; j++) sum[i][j] = sum[i - 1][j]; for (int j = L[i]; j <= R[i]; j++) { belong[j] = i; sum[i][a[j]]++; } } for (int i = 1; i <= bnum; i++) { for (int j = 1; j <= M; j++) cnt[j] = 0; int Ans = 0; for (int j = i; j <= bnum; j++) { for (int k = L[j]; k <= R[j]; k++) { cnt[a[k]]++; Ans += price(cnt[a[k]]) - price(cnt[a[k]] - 1); } F[i][j] = Ans; } } for (int i = 1; i <= M; i++) cnt[i] = 0; for (int i = 1; i <= m; i++) { int l, r; cin >> l >> r; l = l ^ abs(lastans); r = r ^ abs(lastans); if (l > r) swap(l, r); l = max(1, l); l = min(l, n); r = max(1, r); r = min(n, r); if (belong[r] - belong[l] <= 1) { int Ans = 0; for (int j = l; j <= r; j++) { cnt[a[j]]++; Ans += price(cnt[a[j]]) - price(cnt[a[j]] - 1); } cout << Ans << endl; lastans = Ans; for (int j = l; j <= r; j++) cnt[a[j]]--; } else { int Ans = F[belong[l] + 1][belong[r] - 1]; for (int j = l; j <= R[belong[l]]; j++) { cnt[a[j]]++; Ans += price(cnt[a[j]] + sum[belong[r] - 1][a[j]] - sum[belong[l]][a[j]]); Ans -= price(cnt[a[j]] + sum[belong[r] - 1][a[j]] - sum[belong[l]][a[j]] - 1); } for (int j = L[belong[r]]; j <= r; j++) { cnt[a[j]]++; Ans += price(cnt[a[j]] + sum[belong[r] - 1][a[j]] - sum[belong[l]][a[j]]); Ans -= price(cnt[a[j]] + sum[belong[r] - 1][a[j]] - sum[belong[l]][a[j]] - 1); } for (int j = l; j <= R[belong[l]]; j++) cnt[a[j]]--; for (int j = L[belong[r]]; j <= r; j++) cnt[a[j]]--; cout << Ans << endl; lastans = Ans; } } return 0; }