Graph HDU - 4467
https://vjudge.net/problem/HDU-4467
大概就是,设一个块大小T
对于度数<=T的点,设为1类点,在改变颜色的时候暴力查询与其相邻点,更新答案
对于度数>T的点,设为2类点,分别维护与其相邻的颜色为0/1的点之间的边权和(记录与每个点相连的所有2类点,然后在任意点(注意2类点也要)改变颜色时维护一下与其相连2类点的这个值),改变颜色的时候根据维护的值O(1)可以计算出对答案的修改
说的再简单一点,1类点由自身去更新其他,2类点由其他去更新自身。。复杂度很容易发现是根号级别的(T=sqrt(m))
但是要注意,重边一定要去。。。不然可以被卡到$n^2$
错误记录:
1.没有在改变2类点颜色时改变相连其他2类点维护的值
2.没有去重边
3.d[a],d[b]和a,b没有极其仔细地区分
1 //#pragma GCC optimize(3) 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<vector> 6 #include<set> 7 #include<map> 8 using namespace std; 9 #define fi first 10 #define se second 11 #define mp make_pair 12 #define pb push_back 13 typedef long long ll; 14 typedef unsigned long long ull; 15 typedef pair<int,int> pii; 16 #define N 100000 17 struct E 18 { 19 int to,nxt;ll d; 20 }e[2*N+100]; 21 int f1[N+100],ne; 22 int TT,n,m,mm,d[N+100]; 23 int in[N+100],sz,q; 24 //1类点:in[i]<=sz;2类点:in[i]>sz 25 ll a1[N+100][2]; 26 //a1[i][j]:i为2类点,i与相邻的颜色为j的点之间的所有边的权值和 27 //int num[100100]; 28 char tmp[10]; 29 vector<int> ss[N+100];//ss[i]:i点到相邻的2类点的边 30 ll ans[3];//ans[0]:00边答案;ans[1]:11边答案;ans[2]:01边答案 31 map<pii,pii> ma; 32 ll &gg(int a,int b) 33 { 34 if(a==0&&b==0) return ans[0]; 35 if(a==1&&b==1) return ans[1]; 36 return ans[2]; 37 } 38 int main() 39 { 40 int a,b,c,i,k;pii t; 41 while(scanf("%d%d",&n,&m)==2) 42 { 43 TT++;mm=0;//num[0]=0; 44 memset(f1,0,sizeof(f1));ne=0;ma.clear(); 45 memset(in,0,sizeof(in));ans[0]=ans[1]=ans[2]=0; 46 memset(a1,0,sizeof(a1)); 47 for(i=1;i<=n;i++) scanf("%d",&d[i]); 48 for(i=1;i<=m;i++) 49 { 50 scanf("%d%d%d",&a,&b,&c); 51 if(a>b) swap(a,b); 52 if(ma.count(mp(a,b))) 53 { 54 t=ma[mp(a,b)]; 55 e[t.fi].d+=c;e[t.se].d+=c; 56 } 57 else 58 { 59 e[++ne].to=b;e[ne].nxt=f1[a];f1[a]=ne;e[ne].d=c; 60 e[++ne].to=a;e[ne].nxt=f1[b];f1[b]=ne;e[ne].d=c; 61 in[a]++;in[b]++; 62 ma[mp(a,b)]=mp(ne-1,ne);mm++; 63 } 64 gg(d[a],d[b])+=c; 65 } 66 sz=sqrt(2*mm); 67 for(i=1;i<=n;i++) 68 if(in[i]>sz) 69 { 70 //num[++num[0]]=i; 71 for(k=f1[i];k;k=e[k].nxt) 72 a1[i][d[e[k].to]]+=e[k].d; 73 } 74 for(i=1;i<=n;i++) 75 { 76 ss[i].clear(); 77 for(k=f1[i];k;k=e[k].nxt) 78 if(in[e[k].to]>sz) 79 ss[i].pb(k); 80 } 81 scanf("%d",&q); 82 printf("Case %d:\n",TT); 83 while(q--) 84 { 85 scanf("%s",tmp); 86 if(tmp[0]=='A') 87 { 88 scanf("%d%d",&a,&b); 89 printf("%lld\n",gg(a,b)); 90 } 91 else 92 { 93 scanf("%d",&a); 94 if(in[a]<=sz) 95 { 96 for(k=f1[a];k;k=e[k].nxt) 97 { 98 b=e[k].to; 99 gg(d[a],d[b])-=e[k].d; 100 if(in[b]>sz) a1[b][d[a]]-=e[k].d; 101 } 102 d[a]^=1; 103 for(k=f1[a];k;k=e[k].nxt) 104 { 105 b=e[k].to; 106 gg(d[a],d[b])+=e[k].d; 107 if(in[b]>sz) a1[b][d[a]]+=e[k].d; 108 } 109 } 110 else 111 { 112 for(i=0;i<ss[a].size();i++) 113 a1[e[ss[a][i]].to][d[a]]-=e[ss[a][i]].d; 114 gg(d[a],0)-=a1[a][0];gg(d[a],1)-=a1[a][1]; 115 d[a]^=1; 116 gg(d[a],0)+=a1[a][0];gg(d[a],1)+=a1[a][1]; 117 for(i=0;i<ss[a].size();i++) 118 a1[e[ss[a][i]].to][d[a]]+=e[ss[a][i]].d; 119 } 120 } 121 } 122 } 123 return 0; 124 }