首页 > 其他分享 >hdu 3038(种类并查集)

hdu 3038(种类并查集)

时间:2023-05-29 22:39:07浏览次数:43  
标签:fx hdu 3038 int fy 查集 rank fa find


题目大意:有n次询问,给出a到b区间的总和,问这n次给出的总和中有几次是和前面已近给出的是矛盾的


解题思路:这道题第一次接触很难往并查集方向去思考。这里使用的并查集很灵活,不仅仅要记录其父亲节点,同时还要记录该节点到父亲节点的总和。在更新时,[l,r]要变成[l-1,r],比如有区间[1,2],[3,4],在更新[3,4]时可以合并成一个完整区间[1,4],并且在计算[l,r]区间的总和时,是用sum[r] - sum[l-1]来算的。所以这里是用[l-1,r]的原因。




#include<iostream>
#include<cstdio>
#include<cstring>

const int maxn = 200005;
int n,m,ans;
int fa[maxn],rank[maxn];

int find(int x)
{
	if(fa[x] == x) return x;
	int tmp = fa[x];
	fa[x] = find(fa[x]);
	rank[x] += rank[tmp]; 
	return fa[x];
}

void Union(int x,int y,int k)
{
	int fx = find(x);
	int fy = find(y);
	if(fx == fy)
	{
		if(rank[y] - rank[x] != k) ans++;
	}
	else if(fx > fy)
	{
		fa[fx] = fy;
		rank[fx] = rank[y] - rank[x] - k;
	}
	else
	{
		fa[fy] = fx;
		rank[fy] = rank[x] + k - rank[y];
	}
}

int main()
{
	int l,r,k;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		for(int i = 0; i <= n; i++)
			fa[i] = i, rank[i] = 0;
		ans = 0;
		for(int i = 1; i <= m; i++)
		{
			scanf("%d%d%d",&l,&r,&k);
			l--;
			Union(l,r,k);
		}
		printf("%d\n",ans); 
	}
	return 0;
}




标签:fx,hdu,3038,int,fy,查集,rank,fa,find
From: https://blog.51cto.com/u_16143128/6374293

相关文章

  • hdu 2830(矩形dp)
    解题思路:这道题是hdu1505的更加强版本,实际上理解了前面的两道题,这道题很简单了,只是多了一个排序的过程。仔细想想,为什么会是多了排序的过程。因为我们的目标还是找到最大的全1矩阵,那么之前的思路肯定是不变的,关键就在于矩形的列是可以交换的,而且可以交换多次。其实这里不要多去想交......
  • hdu 1506(dp || 单调栈)
    题意:这题是要找最大的矩形面积。解题思路:这题的关键是要找每个条形能够往左和往右能够到达的最大长度。我最开始的思路是单调栈去维护,只要入栈的元素比栈顶元素小,栈顶就要出栈,并且知道其最右能够到达的最远距离。当要入栈的元素已经找到了位置,那么它左边的元素所在的位置就是其能到......
  • hdu 1516(编辑距离+记录路径)
    最开始把问题搞错了,以为是两个串都可以做修改,无论我怎么想都不通。回到这个题目上,这道题和最长公共子序列很相似,思路可以说是一样的,包括记录路径。其实也就是根据递推数组的结果来判断。#include<iostream>#include<cstdio>#include<cstring>usingnamespacestd;constintma......
  • poj 2985(并查集+线段树求K大数)
    解题思路:这道题并查集很容易,合并时找到父节点就直接加上去就ok了。关键是如何求K大数,我一直在想用线段树怎么写,一开始想如果直接记录数的大小那肯定是没戏了,借鉴了一下别人的思路:区间[a,b]记录的是所有的数里面,等于a,a+1,a+2,......,b-1,b的个数。看到这里就应该明白了,这里线段树的用法......
  • hdu 2473(并查集+删除操作)
    解题思路:这道题有并查集的删除操作,如果直接对这一棵树进行删除节点操作肯定是很困难的。所以可以建立虚拟节点,只要有一个节点要被删除,就直接把它投影到虚拟节点上,即用这个虚拟节点来代替我们要删除的节点。这样我们就不需要用对已有的树形结构进行改动了。这个想法我在DragonBalls......
  • hdu 3635(并查集+路径压缩变形)
    解题思路:这道题想了我好久,因为我把城市的编号一起考虑进去了,结果想了好久都没A,最后看了别人的题解居然都没有考虑到城市的编号,不考虑城市编号的问题的话就是一个很水的并查集了。#include<iostream>#include<cstdio>#include<cstring>usingnamespacestd;constintMAXN=1000......
  • hdu 2874(LCA + 节点间距离)
    解题思路:Tarjan离线处理一篇介绍LCA的很好的博客:http://www.cppblog.com/menjitianya/archive/2015/12/10/212447.html#include<iostream>#include<cstdio>#include<cstring>usingnamespacestd;constintmaxn=10005;structEdge{ intk,next,cost;}edge[maxn&......
  • hdu 4027(线段树)
    题意:给定100000个数,两种操作,0ij表示将ij这段的数字都开根号(向下取整),1ij表示查询ij之间的所有值的和。。。(所有的和都不超过64位)解题思路:这题要做区间的开平方操作,2^64最多可以做8次开平方操作,所以对于每个节点最多只有8次操作,这道题如果lazy思想的话就要保存每个区间被开平方......
  • hdu 3564(线段树+LIS)
    题意:给出1~n的插入顺序,要求每次插入之后的LIS解题思路:这道题确实挺难想的,我最开始想用树状数组每插入一个数就更新一次,如果这么想,那么你就输了。它这里的想法是先将1-n的最终位置都保存起来,然后再一个个去找LIS。这里有点离线算法的意思,至少了解到更新时可以先别急着处理。还有这里......
  • hdu 3874(树状数组+离线算法)
    解题思路:这道题和之前的题一样,查找[l,r]区间内不重复数字的和。可以利用离线算法,实际上离线算法为了解决在查找时出现的矛盾,因为每次询问的区间大小不同,如果单独处理的话可能会对之后的查询有影响,所以离线算法帮助我们把要查询的区间先按照右端点进行排序,因为在处理更靠右的区间时,......