HDU4467 Grahp(分块)
这道题与HDU4858 项目管理一样,都是分为轻重点,因为这样只会最多遍历sqrt条边,但是这题需要合并重边,不然复杂度会走样
分块的思想真的很强大。对于轻点来说,暴力遍历更新答案和重信息,而对于重点来说,只需要更新相邻重点。这样做是正确的是因为重点的信息都会由轻点和重点更新,而轻点是暴力,肯定正确。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<cmath> #include<iostream> using namespace std; typedef long long ll; const int N=1e5+10; ll ans[5],a[N]; ll sum[N][2]; int st[N]; int in[N]; int n,m; int cnt; struct node{ int a,b; ll v; bool operator <(const node &t){ if(a==t.a) return b<t.b; return a<t.a; } }s[N]; struct Edge{ int u; ll v; }; vector<Edge> g[N]; int main(){ int h=0; while(cin>>n>>m){ int i; for(i=1;i<=n;i++){ sum[i][0]=sum[i][1]=0; in[i]=0; g[i].clear(); st[i]=0; } memset(ans,0,sizeof ans); for(i=1;i<=n;i++){ scanf("%d",&a[i]); } for(i=1;i<=m;i++){ scanf("%d%d%lld",&s[i].a,&s[i].b,&s[i].v); if(s[i].a>s[i].b) swap(s[i].a,s[i].b); } sort(s+1,s+1+m); cnt=0; int j; for(i=1;i<=m;i=j){ for(j=i+1;j<=m;j++){ if(s[i].a==s[j].a&&s[i].b==s[j].b){ s[i].v+=s[j].v; } else break; } s[++cnt]=s[i]; } int block=sqrt(cnt); for(i=1;i<=cnt;i++){ int x=s[i].a,y=s[i].b; in[x]++; in[y]++; } for(i=1;i<=n;i++){ if(in[i]>block) st[i]=1; } for(i=1;i<=cnt;i++){ int x=s[i].a,y=s[i].b; if(st[x]){ sum[x][a[y]]+=s[i].v; } if(st[y]){ sum[y][a[x]]+=s[i].v; } ans[a[x]+a[y]]+=s[i].v; } for(i=1;i<=cnt;i++){ int x=s[i].a,y=s[i].b; if(st[x]){ if(st[y]){ g[x].push_back(Edge{y,s[i].v}); g[y].push_back(Edge{x,s[i].v}); } else{ g[y].push_back(Edge{x,s[i].v}); } } else{ if(st[y]){ g[x].push_back(Edge{y,s[i].v}); } else{ g[x].push_back(Edge{y,s[i].v}); g[y].push_back(Edge{x,s[i].v}); } } } int q; printf("Case %d:\n",++h); cin>>q; char as[10]; while(q--){ scanf("%s",as); if(as[0]=='A'){ int x,y; scanf("%d%d",&x,&y); printf("%lld\n",ans[x+y]); } else{ int x; scanf("%d",&x); a[x]^=1; if(st[x]){ for(i=0;i<=1;i++){ ans[(a[x]^1)+i]-=sum[x][i]; ans[a[x]+i]+=sum[x][i]; } for(i=0;i<g[x].size();i++){ int j=g[x][i].u; ll h=g[x][i].v; sum[j][a[x]]+=h; sum[j][a[x]^1]-=h; } } else{ for(i=0;i<g[x].size();i++){ int j=g[x][i].u; ll h=g[x][i].v; ans[(a[x]^1)+a[j]]-=h; ans[a[x]+a[j]]+=h; if(st[j]){ sum[j][a[x]]+=h; sum[j][a[x]^1]-=h; } } } } } } }
没有人不辛苦,只有人不喊疼