这种题一般都是差分,而且只用推一层,
所以对于加边和删边就直接差分消除影响即可
注意统计答案的时候还在的边也要统计,相当于做删除处理,扫一遍加边删边即可判断,注意在vector里可能出现多次,只统计一次
码:
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
vector<int>v[200005],chu[200005];
int n,m,ans[200005],i,j,o,cnt[200005],a,b,ci[200005];
char op[5];
int main()
{
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)
{
scanf("%s",op);
if(op[0]=='!')
{
scanf("%d",&o);
cnt[o]++;
}
if(op[0]=='+')
{
scanf("%d%d",&a,&b);
v[a].push_back(b);
ans[b]-=cnt[a];
v[b].push_back(a);
ans[a]-=cnt[b];
}
if(op[0]=='-')
{
scanf("%d%d",&a,&b);
chu[a].push_back(b);
ans[b]+=cnt[a];
chu[b].push_back(a);
ans[a]+=cnt[b];
}
}
for(i=1;i<=n;i++)
{
for(j=0;j<v[i].size();j++)
ci[v[i][j]]=0;
for(j=0;j<v[i].size();j++)
ci[v[i][j]]++;
for(j=0;j<chu[i].size();j++)
ci[chu[i][j]]--;
for(j=0;j<v[i].size();j++)
if(ci[v[i][j]])ans[v[i][j]]+=cnt[i],ci[v[i][j]]=0;
}
for(i=1;i<=n-1;i++)
printf("%d ",ans[i]);
printf("%d",ans[i]);
}