莫队+重点轻点
题意:给你n个点(每个点都有一个颜色,0代表黑色,1代表白色),m条边,每条边有一个权值.现在有有两个操作,一个是修改某个点的颜色(白变成黑/黑变成白),另外一个是询问那些边的两个端点都为指定颜色的权值总和
分析:将所有点分为重点和轻点,但是这次重点和重点之前的边要建在一个图中,剩余的边要建在另一个图中。对于最后访问的颜色,只有三种情况黑+黑(求和为0),黑+白(求和为1),白+白(求和为2),所以用a[0],a[1],a[2]分别对应的答案。对于重点i设置一个sum[i][2],sum[i][0]表示所有与他相邻且颜色为0(黑)的点的边权之和,sum[i][1]同理。更新时,对于重点i来说拿sum[i][0]和sum[i][1]去直接更新a数组,同时将其相邻的重点的sum值进行修改。而对于轻点i来说,遍历所有与i相连的边,暴力更新a数组,而当其相邻点为重点时则需要更新一下重点的sum数组。对于查询操作,直接输出a数组中的值即可

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 #include<cmath> 7 using namespace std; 8 const int M=1e5+10; 9 typedef long long ll; 10 struct node{ 11 ll u,v,w; 12 }a[M]; 13 bool cmp(node p,node q){ 14 if(p.u==q.u) 15 return p.v<q.v; 16 return p.u<q.u; 17 } 18 struct node1{ 19 ll id,w; 20 node1(ll id1=0,ll w1=0):id(id1),w(w1){ 21 } 22 }; 23 vector<node1>g1[M],g2[M]; 24 ll n,m,in[M],zhong[M],sum[M][3],ans[4],col[M]; 25 char s[10]; 26 int main(){ 27 ll sign=1; 28 while(scanf("%lld%lld",&n,&m)!=EOF){ 29 for(int i=1;i<=n;i++){ 30 g1[i].clear(); 31 g2[i].clear(); 32 zhong[i]=0; 33 in[i]=0; 34 sum[i][0]=sum[i][1]=0; 35 } 36 memset(ans,0,sizeof(ans)); 37 //ans[0]=ans[1]=ans[2]=0; 38 for(int i=1;i<=n;i++) 39 scanf("%lld",&col[i]); 40 for(int i=1;i<=m;i++){ 41 scanf("%lld%lld%lld",&a[i].u,&a[i].v,&a[i].w); 42 if(a[i].u>a[i].v) 43 swap(a[i].u,a[i].v); 44 ans[col[a[i].u]+col[a[i].v]]+=a[i].w; 45 } 46 sort(a+1,a+1+m,cmp); 47 ll cnt=0; 48 int i,j; 49 //将重边加在一起; 50 for(i=1;i<=m;i=j){ 51 for(j=i+1;j<=m;j++) 52 if(a[i].u==a[j].u&&a[i].v==a[j].v){ 53 a[i].w+=a[j].w; 54 } 55 else 56 break; 57 a[++cnt]=a[i]; 58 } 59 ll N=(int)sqrt(cnt); 60 for(i=1;i<=cnt;i++){ 61 in[a[i].u]++; 62 in[a[i].v]++; 63 } 64 for(i=1;i<=n;i++){ 65 if(in[i]>N) 66 zhong[i]=1; 67 } 68 for(i=1;i<=cnt;i++){ 69 ll u=a[i].u,v=a[i].v,w=a[i].w; 70 if(zhong[u]){ 71 if(zhong[v]){ 72 g1[u].push_back(node1(v,w)); 73 g1[v].push_back(node1(u,w)); 74 sum[u][col[v]]+=w; 75 sum[v][col[u]]+=w; 76 } 77 else{ 78 g2[v].push_back(node1(u,w)); 79 sum[u][col[v]]+=w; 80 } 81 } 82 else{ 83 if(zhong[v]){ 84 g2[u].push_back(node1(v,w)); 85 sum[v][col[u]]+=w; 86 } 87 else{ 88 g2[u].push_back(node1(v,w)); 89 g2[v].push_back(node1(u,w)); 90 } 91 } 92 } 93 ll P; 94 printf("Case %lld: ",sign++); 95 scanf("%lld",&P); 96 97 98 while(P--){ 99 scanf("%s",s); 100 if(s[0]=='A'){ 101 int x,y; 102 scanf("%d%d",&x,&y); 103 printf("%lld ",ans[x+y]); 104 } 105 else{ 106 int x; 107 scanf("%d",&x); 108 if(zhong[x]){ 109 ans[col[x]+0]-=sum[x][0]; 110 ans[col[x]+1]-=sum[x][1]; 111 ans[1-col[x]+0]+=sum[x][0]; 112 ans[1-col[x]+1]+=sum[x][1]; 113 for(i=0;i<g1[x].size();i++){ 114 ll v=g1[x][i].id,w=g1[x][i].w; 115 sum[v][col[x]]-=w; 116 sum[v][1-col[x]]+=w; 117 118 } 119 } 120 else{ 121 for(i=0;i<g2[x].size();i++){ 122 ll v=g2[x][i].id,w=g2[x][i].w; 123 ans[col[x]+col[v]]-=w; 124 ans[1-col[x]+col[v]]+=w; 125 if(zhong[v]){ 126 sum[v][col[x]]-=w; 127 sum[v][1-col[x]]+=w; 128 } 129 } 130 } 131 col[x]=1-col[x]; 132 } 133 } 134 } 135 return 0; 136 }