chenfy27的刷题记录

导航

abc347E Set Add Query

有数组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);
	int t = 1;
	while (t--) solve();
	return 0;
}

posted on 2024-10-08 21:50  chenfy27  阅读(13)  评论(0)    收藏  举报