题意
给你一张无向图,每条边有权值,点有0/1的权值,一共q个操作:
1. 修改一个点的权值。
2. 询问边两端的点权值为0 0、0 1、1 1的所有边权值和。
题解
首先暴力一点,我们用三个变量aa、ab、bb表示上述询问的三种情况。询问的时候直接输出答案,修改的时候遍历当前点所有的边,修改三个变量即可,但是这样显然是会TLE的,因此我们利用一个分块的思想,将点集合按照点的度分为两个块,度数大于sqrt(m)的分为一块(称为轻点),小于等于的分为另一块(称为重点)。对于重点,我们维护一个have数组,表示当前这个点周围权值是0或1的点,与其连边的权值和。那么对于重点我们通过have数组就可以快速更新三个结果变量,然后我们只需要对重点相连的重点的have数组维护即可,那么对于轻点,我们只需要按照之前的想法暴力修改三个变量与其相连的重点的have数组即可。
AC代码
#include<stdio.h>
#include<vector>
#include<math.h>
#include<map>
#include<string.h>
#define N 100005
using namespace std;
typedef long long ll;
struct node
{
ll to;
ll w;
node(){}
node(ll to,ll w)
{
this->to=to;
this->w=w;
}
};
vector<node>vt[N];
ll a[N],du[N],tot,who[N];
ll have[705][2],nowvt[705][705];
char op[25];
int main()
{
ll n,m,cas=1;
while(~scanf("%lld%lld",&n,&m))
{
memset(nowvt,0,sizeof(nowvt));
memset(have,0,sizeof(have));
ll aa=0,ab=0,bb=0;
tot=0;
ll len=(ll)sqrt(1.0*m);
for(ll i=1;i<=n;i++)
scanf("%lld",&a[i]),vt[i].clear(),du[i]=0;
for(ll i=0;i<m;i++)
{
ll u,v,w;
scanf("%lld%lld%lld",&u,&v,&w);
vt[u].push_back(node(v,w));
vt[v].push_back(node(u,w));
if(!a[u]&&!a[v])aa+=w;
else if(a[u]&&a[v])bb+=w;
else ab+=w;
du[u]++;
du[v]++;
}
for(ll i=1;i<=n;i++)
if(du[i]>len)
who[i]=++tot;
for(ll i=1;i<=n;i++)
{
if(du[i]<=len)continue;
for(ll j=0;j<vt[i].size();j++)
{
ll to=vt[i][j].to;
ll w=vt[i][j].w;
have[who[i]][a[to]]+=w;
if(du[to]>len)
nowvt[who[i]][who[to]]+=w;
}
}
ll q;
scanf("%lld",&q);
printf("Case %lld:\n",cas++);
while(q--)
{
scanf("%s",op);
if(op[0]=='A')
{
ll x,y;
scanf("%lld%lld",&x,&y);
if(!x&&!y)printf("%lld\n",aa);
else if(x&&y)printf("%lld\n",bb);
else printf("%lld\n",ab);
}
else
{
ll u;
scanf("%lld",&u);
if(du[u]<=len)
{
for(ll i=0;i<vt[u].size();i++)
{
ll to=vt[u][i].to;
ll w=vt[u][i].w;
if(du[to]>len)have[who[to]][a[u]]-=w,have[who[to]][a[u]^1]+=w;
if(a[u]==0)
{
if(a[to]==0)aa-=w,ab+=w;
else ab-=w,bb+=w;
}
else
{
if(a[to]==0)ab-=w,aa+=w;
else bb-=w,ab+=w;
}
}
}
else
{
if(a[u]==0)
{
ab-=have[who[u]][1];
aa-=have[who[u]][0];
ab+=have[who[u]][0];
bb+=have[who[u]][1];
}
else
{
ab-=have[who[u]][0];
bb-=have[who[u]][1];
ab+=have[who[u]][1];
aa+=have[who[u]][0];
}
for(ll i=1;i<=tot;i++)
{
have[i][a[u]]-=nowvt[who[u]][i];
have[i][a[u]^1]+=nowvt[who[u]][i];
}
}
a[u]^=1;
}
}
}
}