[CF1229C] Konrad and Company Evaluation

[题目链接]

https://codeforces.com/contest/1229/problem/C

[题解]

维护每个点的可达集合 , 每个点的贡献是 \(in_{u} \cdot out_{u}\) , 在更新时直接维护这个值即可。

这样为什么复杂度正确呢? 考虑势能分析。

将每个点的势能定义为其度数。 将度数不超过 \(\sqrt{N}\) 的点集称为 \(A\) 集 , 其余称为 \(B\) 集。 显然 \(|B| \leq \sqrt{N}\)。

如果操作的点在 \(A\) 集中 , 那么转移的势能不超过 \(\sqrt{N}\)。

如果操作的点在 \(B\) 集中 , 对 \(B\) 集转移的势能是 \(\sqrt{N}\) (\(|B| \leq \sqrt{N}\))。

而对 \(A\) 集转移的势能必然和 \(A\) 给 \(B\) 的势能同级。 总转移量不超过 \(N \sqrt{N}\)。

故时间复杂度 : \(O(N \sqrt{N})\)

[代码]

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

const int MN = 1e6 + 5;

int N , M , deg[MN];
vector < int > g[MN];

inline LL get(int u) {
	return (LL) (g[u].size()) * (deg[u] - g[u].size());
}
int main() {
	
	scanf("%d%d" , &N , &M);
	for (int i = 0; i < M; ++i) {
		int v , u; scanf("%d%d" , &v , &u);
		if (v > u) swap(v , u);
		g[v].emplace_back(u); ++deg[u]; ++deg[v];
	}
	LL ANS = 0;
	for (int i = 1; i <= N; ++i) ANS += get(i);
	printf("%lld\n" , ANS);
	int Q; scanf("%d" , &Q);
	while (Q--) {
		int v; scanf("%d" , &v);
		while (!g[v].empty()) {
			int u = g[v].back();
			ANS -= get(u) + get(v);
			g[v].pop_back(); g[u].emplace_back(v);
			ANS += get(u) + get(v);
		}
		printf("%lld\n" , ANS);
	}
	return 0; 
}
上一篇:python kwargs表达式求值


下一篇:使用“new Function(…)”的安全注意事项(在渲染期间,来自我的Javascript源的表达式)