• ZOJ3742Bellywhite's Algorithm Homework


    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3742

      给定n个点m条边的无向图,支持两个操作:

        C x:将与x相邻的边符号取反。

        Q x:

          如果x为'+',输出正边权和。

          如果x为'-',输出负边权和。

          如果x为'A',输出总边权和。

      按度数分块,将度数≥√m的点记为重点,否则为轻点。

      对于重点,我们记录positive_sum和negative_sum,代表相邻的轻-重边正、负边权和。并且记录与之相邻的重点。

      进行修改操作的时候:

        对于重点的取反,我们打上opp标记,修改时取反并更新一下即可。注意重-重边要单独修改。

        对于轻点的取反,我们暴力修改,注意轻-重边的实际边权是opp*边权即可。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long int64;
    typedef unsigned int uint;
    const int maxn=50015,maxm=100015;
    int n,m,q;
    vector<int> w[maxn];
    bool heavy[maxn],opp[maxn];
    int64 res_p,res_n,sum_p[maxn],sum_n[maxn];
    int tot,deg[maxn],now[maxn],pre[maxm],son[maxm],val[maxm];
    void connect(int u,int v,int w){pre[++tot]=now[u];now[u]=tot;son[tot]=v;val[tot]=w;}
    void initial(){
        res_p=res_n=0;tot=1;
        memset(opp,0,sizeof(opp));
        memset(now,0,sizeof(now));
        memset(deg,0,sizeof(deg));
        memset(heavy,0,sizeof(heavy));
        memset(sum_p,0,sizeof(sum_p));
        memset(sum_n,0,sizeof(sum_n));
        for (int i=1;i<=n;++i) w[i].clear();
    }
    void init(int cases){
        initial();
        if (scanf("%d%d%d",&n,&m,&q)==EOF) exit(0);
        if (cases>1) printf("
    ");
        for (int x,y,v,i=1;i<=m;++i){
            scanf("%d%d%d",&x,&y,&v);
            connect(x,y,v);connect(y,x,v);
            (v>0?res_p:res_n)+=v;++deg[x];++deg[y];
        } 
        for (int lim=sqrt(m),i=1;i<=n;++i) heavy[i]=(deg[i]>lim);
        for (int i=1;i<=n;++i)
            for (int p=now[i];p;p=pre[p])
                if (heavy[i]&&heavy[son[p]]) w[i].push_back(p);
                else (val[p]>0?sum_p[i]:sum_n[i])+=val[p];
    }
    void query(){
        char op[5];scanf("%s",op);
        switch (op[0]){
            case 'A':printf("%lld
    ",res_p+res_n);break;
            case '-':printf("%lld
    ",res_n);break;
            case '+':printf("%lld
    ",res_p);break;
        }
    }
    void opposite(int p){
        (val[p]>0?res_p:res_n)-=val[p];
        val[p]=val[p^1]=-val[p];
        (val[p]>0?res_p:res_n)+=val[p];
    }
    void modify_heavy(int u){
        opp[u]^=1;
        res_p-=sum_p[u];res_n-=sum_n[u];
        swap(sum_p[u],sum_n[u]);sum_p[u]=-sum_p[u];sum_n[u]=-sum_n[u];
        res_p+=sum_p[u];res_n+=sum_n[u];
        for (uint i=0;i<w[u].size();++i) opposite(w[u][i]);
    }
    void modify_light(int u){
        for (int p=now[u];p;p=pre[p]){
            if (heavy[son[p]]){
                int op=opp[son[p]]?-1:1;
                if (op*val[p]>0){
                    res_p-=op*val[p];res_n+=op*-val[p];
                    sum_p[son[p]]-=op*val[p];sum_n[son[p]]+=op*-val[p];
                }
                else{
                    res_n-=op*val[p];res_p+=op*-val[p];
                    sum_n[son[p]]-=op*val[p];sum_p[son[p]]+=op*-val[p]; 
                }
                val[p]=val[p^1]=-val[p];
            }
            else opposite(p);
        }
    }
    void modify(){
        int x;scanf("%d",&x);
        if (heavy[x]) modify_heavy(x);
        else modify_light(x);
    }
    void work(){
        for (int i=1;i<=q;++i){
            char op[5];scanf("%s",op);
            switch (op[0]){
                case 'Q':query();break;
                case 'C':modify();break;
            }
        }
    }
    int cases;
    int main(){
        while (1){init(++cases);work();}
        return 0;
    }
    my code
  • 相关阅读:
    设计模式のIteratorPattern(迭代器模式)----行为模式
    设计模式のChainOfResponsibilityPattern(责任链模式)----行为模式
    设计模式のProxyPattern(代理模式)----结构模式
    设计模式のFlyweight(享元模式)----结构模式
    设计模式のFacadePattern(外观模式)----结构模式
    js代码判断浏览器种类IE、FF、Opera、Safari、chrome及版本
    实现图片预加载
    移动端 下滑时加载新数据
    各种高度
    js验证input输入正整数 和 输入的金额小数点后保留两位(PC端键盘输入)
  • 原文地址:https://www.cnblogs.com/iamCYY/p/4720303.html
Copyright © 2020-2023  润新知