zoukankan      html  css  js  c++  java
  • HDU-3038 How Many Answers Are Wrong 并查集

    题目链接:https://cn.vjudge.net/problem/HDU-3038

    题意

    有一个包含n个整型数字的序列
    现给出一些陈述表示第A个数到第B个数的加和S(即sigma)
    其中有些陈述是对的,有些是错的(在不能判断出对错的情况下,此陈述保证是对的)
    问一共有几个错的陈述

    思路

    还是没有思路,原来有一个前缀和的想法,马上又被自己否定了
    所以经验告诉我,以后有思路了一定要在草稿本上画一画,捋一捋思路
    思路是通过一个并查集来实现区间和,即node[a].pre和a之间的值是node[a].val

    现在考虑如何合并新的线段和
    我们首先要找到需要合并的两个区间的所有端点
    int left=find(a), right=find(b);
    之后只需要把这两个区间中的任意一个端点连在另一个区间的端点上,注意还要把操作的端点值更新一下

    然后考虑如何进行查询
    查询只能在根节点相同的情况下进行,区间和也就是node[b].val-node[a].val

    推广一下就知道有可加可减性的问题,就可以用这个算法

    代码

    #include <cstdio>
    #include <cstring>
    const int maxn=200000+5;
    struct Node{
        int pre, val;
        Node(int pre=0, int val=0):
            pre(pre), val(val) {}
    }node[maxn];
    int n, m;
    int find(int x){
        if (node[x].pre==x) return x;
        int root=find(node[x].pre);
        node[x].val+=node[node[x].pre].val;
        return node[x].pre=root;
    }
    
    int main(void){
        while (scanf("%d%d", &n, &m)==2 && n){
            int a, b, val, cnt=0;
            for (int i=0; i<=n; i++) node[i]=Node(i, 0);
            while (m--){
                scanf("%d%d%d", &a, &b, &val); a--;
                int left=find(a), right=find(b);
                if (left!=right){
                    node[right].pre=left;
                    node[right].val=node[a].val-node[b].val+val;
                }else if (node[b].val-node[a].val!=val) cnt++;
            }printf("%d
    ", cnt);
        }
    
        return 0;
    }
    
    
    Time Memory Length Lang Submitted
    62ms 3072kB 830 G++ 2018-03-22 18:09:55

    > 18-03-23 Update:更新思路
  • 相关阅读:
    python2和python3中TestSuite().addTest的区别
    python2和python3中range的区别
    WebDriverAgent安装
    Charles IOS https抓包
    Python和 pytest的异常处理
    Python中yaml和json文件的读取和应用
    Python 获取当前文件所在路径
    自建包函数调用
    python的logging,将log保存到文件
    泛型
  • 原文地址:https://www.cnblogs.com/tanglizi/p/8627650.html
Copyright © 2011-2022 走看看