题意很简单。就是两个操作
1、要么翻转某个点的标号。
2、要么询问某组边的权值一共为多少,总共有三种类型的边:端点分别为(0, 0), (0, 1), (1, 1)。
显然暴力超时。。这时候就用到了块状性质。
假设度数 > Sqrt(m) 的节点为重节点, 度数 <= Sqrt(m) 的节点为轻节点。。
可以知道 重节点数 <= Sqrt(m) , 轻节点暴力修改时复杂度为 Sqrt(m)
修改操作:
如果是轻节点, 暴力修改周围节点, 如果周围节点有 重节点,就维护该值 , 复杂度 O(sqrt(m))
如果是重节点 , 只用维护与它相连的重节点,可知重节点不超过O(sqrt(m)), 复杂度O(sqrt(m))
查询操作:
直接输出答案 O(1)
#include <cstdio>
#include <cstdlib>
#include <map>
#include <set>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <sstream>
#include <math.h>
#define mp(x,y) make_pair(x,y)
#define pii pair<int,int>
#define pLL pair<long long ,long long>
#define pb(x) push_back(x)
#define rep(i,j,k) for(int i = j; i < k;i++)
#define MAX(x,a) x=((x)<(a))?(a):(x);
#define MIN(x,a) x=((x)>(a))?(a):(x);
using namespace std;
int Sqrt = 333;
const int N = 100210;
int n,m,q;
map<pii ,long long>M;
int is[N],a[N],wei[500000];
int ne[500000],to[500000];
long long g[700][700];
int head[N];
int deg[N];
int tot,cnt;
long long f[800][4];
long long ans[10];
void addedge(int u,int v,int w){
ne[tot] = head[u],to[tot]=v, wei[tot] = w , head[u] = tot++;
}
void init(){
Sqrt = (int)sqrt(1.0*m);
M.clear();
cnt = tot = 0;
memset(g,0,sizeof(g));
memset(is,0xff,sizeof(is));
memset(head,0xff,sizeof(head));
memset(ans,0,sizeof(ans));
memset(f,0,sizeof(f));
memset(deg,0,sizeof(deg));
rep(i,0,n) scanf("%d",a+i);
rep(i,0,m){
int u,v,w;
scanf("%d %d %d",&u,&v,&w); u--,v--;
if(u>v)swap(u,v);
ans[a[u]+a[v]] += w;
if(M.count(mp(u,v))) M[mp(u,v)]+=w;
else{
M[mp(u,v)]+=w;
deg[u]++,deg[v]++;
}
}
rep(i,0,n){
if(deg[i]>Sqrt)
is[i] = cnt++;
}
}
void deal(){
map<pii , long long>::iterator it = M.begin();
for( ; it != M.end(); it++){
int u = it->first.first , v = it->first.second;
if(~is[u] && ~is[v]){ // 都是度数>Sqrt的
g[is[u]][is[v]] += it->second;
g[is[v]][is[u]] += it->second;
f[is[u]][a[v]] += it->second;
f[is[v]][a[u]] += it->second;
}else if(~is[u]){ // u 是
f[is[u]][a[v]] += it->second;
addedge(v,u,it->second);
}else if(~is[v]){ // v 是
f[is[v]][a[u]] += it->second;
addedge(u,v,it->second);
}else{
addedge(u,v,it->second);
addedge(v,u,it->second);
}
}
}
void modify(int u){
if(~is[u]){ // 是 重度数
ans[a[u]] -= f[is[u]][0] , ans[1-a[u]] += f[is[u]][0];
ans[1+a[u]] -= f[is[u]][1] , ans[2-a[u]] += f[is[u]][1];
rep(i,0,cnt)
f[i][a[u]] -= g[is[u]][i] , f[i][1-a[u]] += g[is[u]][i];
}else{ // 不是重度数
for(int i = head[u] ; i != -1; i = ne[i]){
int v = to[i] , w = wei[i];
if(~is[v]){
f[is[v]][a[u]] -= w;
f[is[v]][1-a[u]] += w;
}
ans[a[u]+a[v]] -= w;
ans[1-a[u]+a[v]] += w;
}
}
a[u] ^= 1;
}
int main(){
int tt = 0;
while(scanf("%d %d",&n,&m)!=EOF){
init();
deal();
scanf("%d",&q);
char op[20]; int l,r;
printf("Case %d:\n",++tt);
while(q--){
scanf("%s",op);
if(op[0] == 'A'){
scanf("%d %d",&l,&r);
printf("%I64d\n",ans[l+r]);
}else{
scanf("%d",&l); l--;
modify(l);
}
}
}
return 0;
}