abc347E Set Add Query

chenfy27發表於2024-10-08

有陣列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;
}

相關文章