HDU4467 Grahp(分块)

这道题与HDU4858 项目管理一样,都是分为轻重点,因为这样只会最多遍历sqrt条边,但是这题需要合并重边,不然复杂度会走样

分块的思想真的很强大。对于轻点来说,暴力遍历更新答案和重信息,而对于重点来说,只需要更新相邻重点。这样做是正确的是因为重点的信息都会由轻点和重点更新,而轻点是暴力,肯定正确。

#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:
",++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
",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;
                        }
                    }
                }
            }
        }
    }
}
View Code
原文地址:https://www.cnblogs.com/ctyakwf/p/12575481.html