HDU-3038 How Many Answers Are Wrong(带权并查集区间合并)

http://acm.hdu.edu.cn/showproblem.php?pid=3038

大致题意:

有一个区间[0,n],然后会给出你m个区间和,每次给出a,b,v,表示区间[a,b]的区间和为v,但每次给出的区间可能与之前的有冲突,问这样起冲突的区间共有多少个

首先区间[a,b]的和可由区间[0,b]的和减去区间[0,a-1]的和得到

但是我们不太可能知道[0,b],故我们只用知道和b的合并过的区间的左端点就行

其实并查集实质就是一颗树,我们可以以树的角度去看待它,理解维护过程

不理解的同学可以在纸上多划几遍,理解过程

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <iostream>
 4 #include <string>
 5 #include <math.h>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <stack>
 9 #include <queue>
10 #include <set>
11 #include <map>
12 #include <sstream>
13 const int INF=0x3f3f3f3f;
14 typedef long long LL;
15 const int mod=1e9+7;
16 const int maxn=1e5+10;
17 using namespace std;
18
19 int fa[200005];//fa[i] 存i的最左端点
20 int sum[200005];//记录i到根节点之间和的差值,若再跟节点右侧 则为负数
21
22 void init(int n)
23 {
24     for(int i=0;i<=n;i++)
25         fa[i]=i;
26 }
27 int Find(int x)//带权并查集,此时find不单有查找任务,还有更新距离任务
28 {
29     if(x!=fa[x])
30     {
31         int t=fa[x];//记录之前的父节点
32         fa[x]=Find(fa[x]);//路径压缩
33         sum[x]+=sum[t];//递归维护sum
34     }//记录到根节点的距离,根节点是一个区间的一个端点而不是一个区间,输入的区间被合并成了两个点
35     return fa[x];
36 }
37
38 int main()
39 {
40     #ifdef DEBUG
41     freopen("sample.txt","r",stdin);
42     #endif
43 //    ios_base::sync_with_stdio(false);
44 //    cin.tie(NULL);
45
46     int n,m;
47     while(~scanf("%d %d",&n,&m))
48     {
49         init(n);
50         memset(sum,0,sizeof(sum));
51         int ans=0;
52         for(int i=1;i<=m;i++)
53         {
54             int l,r,v;
55             scanf("%d %d %d",&l,&r,&v);//
56             int x=Find(l-1); //注意为什么要-1
57             int y=Find(r);
58             if(x!=y)//如果不是一个集合 合并
59             {
60                 fa[y]=x;
61                 sum[y]=sum[l-1]-sum[r]+v;
62             }
63             else if(sum[r]-sum[l-1]!=v) ans++;//当有相同的最左端时,直接判断
64         }
65         printf("%d\n",ans);
66     }
67
68     return 0;
69 }

-

原文地址:https://www.cnblogs.com/jiamian/p/12256619.html

时间: 2024-10-07 21:14:33

HDU-3038 How Many Answers Are Wrong(带权并查集区间合并)的相关文章

HDU 3038 How Many Answers Are Wrong 带权并查集

分析:这一题和HDU3047一样,都是带权并查集,求后输入和先输入的冲突个数 然后其实就是用并查集维护一棵树,小的作为大的祖先,然后这棵树每个节点到根的路径权值是相对根节点的距离 这样就可以维护距离限制,判断冲突 #include <cstdio> #include <cstring> #include <queue> #include <set> #include <map> #include <stack> #include &l

hdu 3038 How Many Answers Are Wrong ( 带 权 并 查 集 )

How Many Answers Are Wrong Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2961    Accepted Submission(s): 1149 Problem Description TT and FF are ... friends. Uh... very very good friends -_____

HDU 3038 How Many Answers Are Wrong (带权并查集+区间判断)

题意:给你长度为n的区间,m个询问:a,b,c,问这m个问题有多少个是错误的(矛盾). 10 5 1 10 100 7 10 28 1 3 32 4 6 41 6 6 1 由6->6=1,  4->6=41 知4->5=40; 同理 由1->10=100,7->10=28 知1->7=72; 又由1->3=32,4-6=41 知1->7=73,与上面矛盾: 所以答案为1: #include<cstdio> #include<stdlib.h

HDU3038 How Many Answers Are Wrong[带权并查集]

How Many Answers Are Wrong Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6336    Accepted Submission(s): 2391 Problem Description TT and FF are ... friends. Uh... very very good friends -_____

hdu 3038 How Many Answers Are Wrong(种类并查集)

了解了种类并查集,同时还知道了一个小技巧,这道题就比较容易了. 其实这是我碰到的第一道种类并查集,实在不会,只好看着别人的代码写.最后半懂不懂的写完了.然后又和别人的代码进行比较,还是不懂,但还是交了. 现在回过头来看,又看了一遍. 题意—— 输入—— 给出多组测试数据. 每组数据第一行包含两个整数n, m.n表示共有1——n这么多个数,m表示m组提示. 接下来m行,每行包含三个整数a, b, val.表示从a到b这几个数的和为val. 这几组数有可能有冲突,问一共有多少组有冲突的数据. 输出—

HDU3038:How Many Answers Are Wrong(带权并查集)

How Many Answers Are Wrong Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 16338    Accepted Submission(s): 5724 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3038 Description: TT and FF are ..

HDU Virtual Friends(超级经典的带权并查集)

Virtual Friends Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 11092    Accepted Submission(s): 3221 Problem Description These days, you can do all sorts of things online. For example, you can

并查集例题02.带权并查集(poj1182)

Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A.现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种.有人用两种说法对这N个动物所构成的食物链关系进行描述:第一种说法是"1 X Y",表示X和Y是同类.第二种说法是"2 X Y",表示X吃Y.此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的.当一句话满足下列三条之一时,这句

HDU - 3038 How Many Answers Are Wrong (带权并查集)

题意:n个数,m次询问,每次问区间a到b之间的和为s,问有几次冲突 思路:带权并查集的应用,[a, b]和为s,所以a-1与b就可以确定一次关系,通过计算与根的距离可以判断出询问的正确性 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 200010; int f[MAXN],a