传送门:Hdu 4467 Graph
题意:给你n个点,m条边,每条边有一个权值,有两个操作,一个是修改单点的颜色,一个是询问边的两个端点都为指定颜色的权值和
思路:
对点进行分块,度数大于等于根号n的点称为重点,
否则称为轻点
对于轻点,存下与其相连的所有的边,对于重点,只存下与这个重点相连的重点的边对于一个点的更新,如果这个点是轻点,暴力更新与其相连的所有点
如果是重点,那么只需要更新与其相连的终点就可以了(因为如果连的是轻点,轻点更新的时候自然会更新这个点,而不会造成一条边的两个点都更新了,而这条边没有更新的情况)
对于与其相连的轻点,改变一下每个点记录的sum就可以了
#include<bits/stdc++.h>
using namespace std;
const int maxn=100100;
int color[maxn],degree[maxn],key[maxn];
struct Edge{
int from,to;
long long len;
}E[maxn*2];
vector<int>G[maxn];
vector<long long>c[maxn];
long long ans[3],sum[maxn][2];
bool cmp(Edge u,Edge v){
if(u.from!=v.from)
return u.from<v.from;
return u.to<v.to;
}
char s[10];
void change(int u){
if(key[u])
for(int i=0;i<G[u].size();i++){
sum[G[u][i]][color[u]]-=c[u][i];
sum[G[u][i]][color[u]^1]+=c[u][i];
}
else{
sum[u][0]=0,sum[u][1]=0;
for(int i=0;i<G[u].size();i++){
sum[u][color[ G[u][i] ]]+=c[u][i];
if(key[ G[u][i] ]){
sum[G[u][i]][color[u]]-=c[u][i];
sum[G[u][i]][color[u]^1]+=c[u][i];
}
}
}
if(color[u]==0){
ans[0]-=sum[u][0],ans[1]+=(sum[u][0]-sum[u][1]);
ans[2]+=sum[u][1];
color[u]^=1;
}
else{
ans[0]+=sum[u][0],ans[1]+=(sum[u][1]-sum[u][0]);
ans[2]-=sum[u][1];
color[u]^=1;
}
}
int main(){
int n,m,case1=1;
while(scanf("%d%d",&n,&m)!=EOF){
printf("Case %d:\n",case1++);
for(int i=1;i<=n;i++)
scanf("%d",&color[i]),c[i].clear(),G[i].clear();
int u,v;
for(int i=1;i<=m;i++){
scanf("%d%d%lld",&E[i].from,&E[i].to,&E[i].len);
if(E[i].from>E[i].to)
swap(E[i].from,E[i].to);
}
sort(E+1,E+m+1,cmp);
int tot=0;
E[++tot]=E[1];
for(int i=2;i<=m;i++){
if(E[tot].from==E[i].from&&E[i].to==E[tot].to)
E[tot].len+=E[i].len;
else
E[++tot]=E[i];
}
memset(ans,0,sizeof(ans));
memset(sum,0,sizeof(sum));
memset(key,0,sizeof(key));
memset(degree,0,sizeof(degree));
for(int i=1;i<=tot;i++){
degree[E[i].from]++,degree[E[i].to]++;
sum[E[i].from][color[E[i].to]]+=E[i].len;
sum[E[i].to][color[E[i].from]]+=E[i].len;
ans[color[E[i].to]+color[E[i].from]]+=E[i].len;
}
int unit=sqrt(n);
for(int i=1;i<=n;i++)
if(degree[i]>unit)
key[i]=1;
for(int i=1;i<=tot;i++){
u=E[i].from,v=E[i].to;
if(key[u]&&key[v]){ //轻链存着所有边,重链只存重链
G[u].push_back(v),c[u].push_back(E[i].len);
G[v].push_back(u),c[v].push_back(E[i].len);
}
if(key[u]==0)
G[u].push_back(v),c[u].push_back(E[i].len);
if(key[v]==0)
G[v].push_back(u),c[v].push_back(E[i].len);
}
int q;
scanf("%d",&q);
for(int i=1;i<=q;i++){
scanf("%s",s);
if(s[0]=='C')
scanf("%d",&u),change(u);
else{
scanf("%d%d",&u,&v);
printf("%lld\n",ans[u+v]);
}
}
}
return 0;
}