cf1037E

 

 题解:考虑逆序处理询问,用一个set来维护能去的人,每次减少边的时候,维护一下这个set就可以,具体看代码

int main(){
	int n, m, k;
	cin >> n >> m >> k;
	vector<pair<int, int> > Edges(m);
	vector<int> Ans(m);
	vector<int> degree(n,0);
	vector<vector<pair<int, int> > > adj(n);
	set<pair<int, int> > Good_set;
	vector<int> in_good_set(n, true);
	for (int i = 0; i<m; i++){
		cin >> Edges[i].first >> Edges[i].second;
		Edges[i].first--;
		Edges[i].second--;
		adj[Edges[i].first].push_back({ Edges[i].second,i });
		adj[Edges[i].second].push_back({ Edges[i].first,i });
		degree[Edges[i].first]++;
		degree[Edges[i].second]++;
	}
	for (int i = 0; i<n; i++){
		Good_set.insert({ degree[i],i });
	}
	while (!Good_set.empty() && Good_set.begin()->first<k)	{
		int node = Good_set.begin()->second;
		for (auto &y : adj[node]){
			int x = y.first;
			if (in_good_set[x]){
				Good_set.erase({ degree[x],x });
				--degree[x];
				Good_set.insert({ degree[x],x });
			}
		}
		Good_set.erase({degree[node],node});
		in_good_set[node] = false;
	}

	for (int i = m - 1; i >= 0; i--)
	{
		Ans[i] = Good_set.size();

		int u = Edges[i].first, v = Edges[i].second;
		if (in_good_set[u] && in_good_set[v])
		{
			Good_set.erase({ degree[u],u });
			--degree[u];
			Good_set.insert({ degree[u],u });

			Good_set.erase({ degree[v],v });
			--degree[v];
			Good_set.insert({ degree[v],v });

			while (!Good_set.empty() && Good_set.begin()->first<k)
			{
				int node = Good_set.begin()->second;
				for (auto &y : adj[node])
				{
					int x = y.first;
					if (y.second >= i) //非常重要
						continue;
					if (in_good_set[x])
					{
						Good_set.erase({ degree[x],x });
						--degree[x];
						Good_set.insert({ degree[x],x });
					}
				}
				Good_set.erase({degree[node],node});
				in_good_set[node] = false;
			}
		}
	}
	for (int i = 0; i<m; i++)
		cout << Ans[i] << "\n";
}

  

posted on 2020-02-21 21:58  欣崽  阅读(173)  评论(0编辑  收藏  举报

导航