题面
题意
给出一张无向图,每个点有一个颜色(0或者1),每条边有一个权值,要求支持两种两种操作:
1.改变某个点的颜色
2.询问边的两端为某两种颜色的边权之和(一共只有三种询问,(0,0),(0,1),(1,1))。
做法
这题看上去无从下手,但是上做法十分暴力,首先预处理出每种询问的答案,每次操作只要对其修改即可。
将点按其度数大小将其分为两类:
1.度数大于sqrt(m)
2.度数小于等于sqrt(m)
对于第一种点每次都直接遍历显然不行,应该分别预处理出与它相连的所有白点和黑点的边权和,当周围点的颜色改变时,也同时需要更改它的信息,因此也要在修改它时也同样需要修改与它直接相连的第一种点的信息。
对于第二种点,每次只要暴力修改与它相连的第一种点,暴力查询即可。
注意:需要去掉重边,否则可能所有点都是第一种点,稳T。
代码
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cmath>
#define ll long long
#define P pair<ll,ll>
#define mp make_pair
#define fi first
#define se second
#define C ch=getchar()
#define N 100100
#define D 20000000
using namespace std;
ll T,n,m,Q,ds[N],s,cnt[N][2],ans[3],first[N],f2[N],bb,b2,xh,a[N],b[N],c[N];
bool dn[N];
char ch;
struct Bn
{
ll to,nxt,quan;
} bn[N<<1],bn2[N<<1];
inline ll read()
{
static ll res;
for(C; ch<'0'||ch>'9'; C);
for(res=ch-'0',C; ch>='0'; res=res*10+ch-'0',C);
return res;
}
inline void write(ll u)
{
if(u>9) write(u/10);
putchar(u%10+'0');
}
inline void add(ll u,ll v,ll w)
{
bb++;
bn[bb].to=v;
bn[bb].quan=w;
bn[bb].nxt=first[u];
first[u]=bb;
}
inline void ad2(ll u,ll v,ll w)
{
b2++;
bn2[b2].to=v;
bn2[b2].quan=w;
bn2[b2].nxt=f2[u];
f2[u]=b2;
}
int main()
{
ll i,j,p,q,o,tmp;
while(scanf("%lld%lld",&n,&m)==2)
{
bb=b2=0;
memset(first,-1,sizeof(first));
memset(f2,-1,sizeof(f2));
memset(ds,0,sizeof(ds));
memset(cnt,0,sizeof(cnt));
ans[0]=ans[1]=ans[2]=0;
printf("Case %lld:\n",++T);
s=sqrt(n)*2;
for(i=1; i<=n; i++) dn[i]=read();
for(i=1;i<=m;i++)
{
a[i]=read(),b[i]=read(),c[i]=read();
if(a[i]>b[i]) swap(a[i],b[i]);
ans[dn[a[i]]+dn[b[i]]]+=c[i];
}
for(i=1,tmp=0; i<=m; i++)
{
tmp+=c[i];
if(i==m || a[i]!=a[i+1] || b[i]!=b[i+1])
{
ds[a[i]]++,ds[b[i]]++;
add(a[i],b[i],tmp);
add(b[i],a[i],tmp);
tmp=0;
}
}
for(i=1; i<=n; i++)
{
if(ds[i]>s)
{
for(j=first[i]; j!=-1; j=bn[j].nxt)
{
p=bn[j].to,q=bn[j].quan;
cnt[i][dn[p]]+=q;
if(ds[p]>s)
ad2(i,p,q);
}
}
}
Q=read();
for(i=1; i<=Q; i++)
{
for(C; ch!='A'&&ch!='C'; C);
if(ch=='A')
{
write(ans[read()+read()]);
puts("");
}
else
{
o=read();
if(ds[o]<=s)
{
for(j=first[o]; j!=-1; j=bn[j].nxt)
{
p=bn[j].to,q=bn[j].quan;
if(ds[p]>s)
{
cnt[p][dn[o]]-=q;
cnt[p][dn[o]^1]+=q;
}
ans[dn[o]+dn[p]]-=q;
ans[(dn[o]^1)+dn[p]]+=q;
}
}
else
{
ans[dn[o]]-=cnt[o][0];
ans[dn[o]^1]+=cnt[o][0];
ans[dn[o]+1]-=cnt[o][1];
ans[(dn[o]^1)+1]+=cnt[o][1];
for(j=f2[o]; j!=-1; j=bn2[j].nxt)
{
p=bn2[j].to,q=bn2[j].quan;
cnt[p][dn[o]]-=q;
cnt[p][dn[o]^1]+=q;
}
}
dn[o]^=1;
}
}
}
}