有数组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;
}