首先根据题目所给的图片,我们其实可以发现,答案就是枚举每个点,以这个点作为中间节点的答案
这也就是意味着,我们刚开始按权值大小从大到小连边,答案就是入度*出度。而对于每次修改,就是去除这个点的贡献,同时修改他旁边点的贡献
这样能够保证复杂度的原因是,一旦我这个点被清空了,那么连边就没了。即使我们每次都枚举不同的点,那么单次操作复杂度大概也是在根号n左右
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int inf=0x3f3f3f3f; const int N=1e5+10; const int mod=1e9+7; int in[N]; vector<int> g[N]; ll cal(int x){ return (ll)g[x].size()*(in[x]-(ll)g[x].size()); } int main(){ ios::sync_with_stdio(false); int n,m; cin>>n>>m; int i; for(i=1;i<=m;i++){ int a,b; cin>>a>>b; if(a>b) swap(a,b); g[a].push_back(b); in[a]++,in[b]++; } ll ans=0; for(i=1;i<=n;i++){ ans+=cal(i); } int t; cin>>t; cout<<ans<<endl; while(t--){ int x; cin>>x; ans-=cal(x); for(auto b:g[x]){ ans-=cal(b); g[b].push_back(x); ans+=cal(b); } g[x].clear(); cout<<ans<<endl; } return 0; }