有陣列A[N],初始時元素都為0,另外還有初始為空的集合S。依次處理以下Q組查詢:給出整數x[i],如果S包含x[i],則從S中移除x[i],否則將x[i]加入S,記此時S的大小為|S|,把|S|加到集合中的每個元素i對應的A[i]中。求最終A[i]是多少。
1<=N,Q<=2E5; 1<=x[i]<=N
分析:記錄每個時刻集合S的大小,設元素u在t1時刻加入集合,在t2時刻移出集合,那麼[t1,t2)區間各個時刻集合的大小都要加到u對應的答案中,因此用字首和維護集合大小。
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int N, Q;
std::cin >> N >> Q;
std::vector<i64> A(Q + 1);
for (int i = 1; i <= Q; i++) {
std::cin >> A[i];
}
std::set<i64> st;
std::vector<i64> cnt(Q + 1);
for (int i = 1; i <= Q; i++) {
if (st.count(A[i])) {
st.erase(A[i]);
} else {
st.insert(A[i]);
}
cnt[i] = st.size();
}
std::partial_sum(cnt.begin(), cnt.end(), cnt.begin());
auto sum = [&](int l, int r) {
return l <= r ? cnt[r] - cnt[l - 1] : 0;
};
std::set<int> st1;
std::vector<int> lst(Q + 1);
std::vector<i64> ans(Q + 1);
for (int i = 1; i <= Q; i++) {
if (st1.count(A[i])) {
ans[A[i]] += sum(lst[A[i]], i - 1);
st1.erase(A[i]);
} else {
st1.insert(A[i]);
lst[A[i]] = i;
}
}
for (auto i : st1) {
ans[i] += sum(lst[i], Q);
}
for (int i = 1; i <= N; i++) {
std::cout << ans[i] << " \n"[i == N];
}
}
int main() {
std::cin.tie(0)->sync_with_stdio(0);
std::cout << std::fixed << std::setprecision(10);
int t = 1;
while (t--) solve();
return 0;
}