zoukankan      html  css  js  c++  java
  • HDU 3038 How Many Answers Are Wrong(带权并查集)

    太坑人了啊,读入数据a,b,s的时候,我刚开始s用的%lld,给我WA。 实在找不到错误啊,后来不知怎么地突然有个想法,改成%I64d,竟然AC了

    思路:我建立一个sum数组,设i的父亲为fa,sum[i]表示(fa,i]中的数的和(不包括fa,包括i),    

      合并的时候,不是合并a,b,而是合并a-1,b。这样做的目是因为s是[a,b]的和,如果直接合并a,b,那么按照我数组的定义应该是(a,b]的和,这样不符合题意。    

      接下来,每次读入a,b,只要根据他们父节点的不同情况分类讨论即可。

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    
    const int maxn=200010;
    int father[maxn];
    long long sum[maxn]; //设i的父亲为fa,sum[i]表示(fa,i]中的数的和(不包括fa,包括i)
    int n,m;
    void init() {
        for(int i=0; i<=n; i++) {
            father[i]=i;
            sum[i]=0;
        }
    }
    
    int find_root(int x) {
        if(father[x]==x)
            return x;
        int fa=father[x];
        father[x]=find_root(father[x]);
        sum[x]=(sum[x]+sum[fa]);
        return father[x];
    }
    //合并的时候,保证x<y
    void Union(int x,int y) {
        father[y]=x;
    }
    int main() {
        int a,b,ans=0;
        long long s;
        while(scanf("%d%d",&n,&m)!=EOF) {
            init(); //怎么老忘记写这个啊
            ans=0;
            for(int i=1; i<=m; i++) {
                scanf("%d%d%I64d",&a,&b,&s);   //就是这里,本来用的是lld的格式,导致WA
                int fa=find_root(a-1);
                int fb=find_root(b);
                /*
                fa=fb时,(fa,a-1]=sum[a-1],(fb,b]=sum[b],
                         ——>[a,b]=sum[b]-sum[a-1],显然即应该等于s
                         若不等于,即使错误的
                */
                if(fa==fb) {
                    if(sum[b]-sum[a-1]!=s) {
                        ans++;
                    }
                }
                else {
                    if(fb>a-1) {
                        /*
                        大小关系:fa<=a-1<fb<=b
                        (fa,a-1]=sum[a-1],[a,b]=s,(fb,b]=sum[b];
                        ——>[a,fb]=s-sum[b],
                           (fa,fb]=(fa,a-1]+[a-1,fb]=sum[a-1]+s-sum[b];
                        */
                        Union(fa,fb);
                        //更新fb的父节点fa到fb区间的和(不包括fa)
                        sum[fb]=sum[a-1]+s-sum[b];
                    } else if(fb==a-1) {
                        /*
                        大小关系:fa<=a-1=fb<=b
                        (fa,a-1]=sum[a-1],[a,b]=s,(fb,b]=sum[b];
                         ——>sum[b]即为[a,b]的和。
                         若sum[b]不等于s,说明错误
                         如果相同,则合并
                        */
                        if(s!=sum[b]) {
                            ans++;
                        } else {
                            Union(fa,fb);
                            sum[fb]=sum[a-1];
                        }
                    }
                    //fb<a-1
                    else {
                        if(fb>fa) {
                        /*
                        大小关系:fa<fb<a-1<b
                        (fb,b]=sum[b],(a-1,b]=s ——>(fb,a-1]=sum[b]-s;
                        再由(fa,a-1]=sum[a-1]——>(fa,fb]=sum[a-1]-sum[b]+s;
                        */
                            Union(fa,fb);
                            sum[fb]=sum[a-1]-sum[b]+s;
                        }
                        else {
                        /*
                        大小关系:fb<fa<=a-1<=b
                        (fb,b]=sum[b],(a-1,b]=s,(fa,a-1]=sum[a-1];
                         ——>(fa,b]=s+sum[a-1]
                         ——>(fb,fa]=sum[b]-s-sum[a-1];
                        */
                            Union(fb,fa);
                            sum[fa]=sum[b]-s-sum[a-1];
                        }
    
                    }
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    wget: command not found
    小程序循环多个picker选择器,实现动态增、减
    小程序 picker 多列选择器 数据动态获取
    有关https有的网站可以访问有的访问不了的问题
    微信小程序填坑之路
    linux如何搭建sftp服务器
    微信小程序模板中使用循环
    C#学习笔记(20)——使用IComparer(自己写的)
    C#学习笔记(19)——使用IComparer(百度文库)
    C#学习笔记(18)——C#构造函数中this和base的使用
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/3297564.html
Copyright © 2011-2022 走看看