首页 > 其他分享 >动态开点并查集+树上差分

动态开点并查集+树上差分

时间:2024-03-21 16:11:54浏览次数:28  
标签:int 查集 long fa 差分 开点 root find define

https://www.acwing.com/problem/content/description/2071/

每次合并的时候需要开一个新点去实现信息的无后效性,也就是合并之前的两个连通块信息是无法共享的,发现这样开点连边最后

形成一棵树,每次我们将信息传递到新点,也是两个合并点的lca,这使得最后求答案的直接求一边树上前缀和,不同子树不受影响

debug:最后合并n-1次,初始化和空间都要开两倍

// Problem: 网络分析
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/2071/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
//# define int long long
#define ull unsigned long long
#define pii pair<int,int>

#define baoliu(x, y) cout << fixed << setprecision(y) << x
#define endl  "\n"
#define debug1(x) cerr<<x<<" "
#define  debug2(x) cerr<<x<<endl
const int N = 2e4 + 10;
const int M = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const int mod = 998244353;
const double eps = 1e-8;
int n, m;
int a[N];
int fa[N];
int sz[N];
vector<int>e[N];

int find(int x){
	if(x!=fa[x])fa[x]=find(fa[x]);
	return fa[x];
}
//并不是简单并查集,因为还涉及信息的历史性,也就是后来进入的节点是没有办法享用之前
//的信息的
//动态开点并查集+树上差分?

void dfs(int u,int fa){
	sz[u]+=sz[fa];
	for(auto v:e[u]){
		if(v==fa)continue;
		dfs(v,u);
		//sz[v]+=sz[u];
	}
}
void solve(){
	//for(int i=1;i<=n;i++)fa[i]=i;
	cin>>n>>m;
	int root=n+1;
		for(int i=1;i<=n*2;i++)fa[i]=i;
	for(int i=1;i<=m;i++){
		int op;cin>>op;
		if(op==1){
			int u,v;cin>>u>>v;
			u=find(u),v=find(v);
			if(u==v)continue;
			fa[u]=fa[v]=root;
			
			e[root].push_back(u);
			e[root].push_back(v);
			root++;
		}
		else {
			int v;cin>>v;
			v=find(v);
			int val;cin>>val;
			sz[v]+=val;
		}
	}
	for(int i=1;i<=2*n;i++){
		if(fa[i]==i)dfs(i,0);
	}
	for(int i=1;i<=n;i++)cout<<sz[i]<<" ";
}
int main() {
    cin.tie(0);
    
    ios::sync_with_stdio(false);

    int t;
   //cin>>t;
     t=1;
    while (t--) {
solve();
    }
    return 0;
}

``

标签:int,查集,long,fa,差分,开点,root,find,define
From: https://www.cnblogs.com/mathiter/p/18087608

相关文章

  • 数据结构(七)并查集---以题为例
    一共有 n 个数,编号是 1∼n,最开始每个数各自在一个集合中。现在要进行 m 个操作,操作共有两种:Mab,将编号为 a 和 b 的两个数所在的集合合并,如果两个数已经在同一个集合中,则忽略这个操作;Qab,询问编号为 a 和 b 的两个数是否在同一个集合中;输入格式第一行输入整......
  • 二维前缀和&二维差分(超详细,python版,其他语言也很轻松能看懂)
    上一篇文章讲解了一维前缀和&一维差分,本篇进阶为二维。二维前缀和:二维前缀和跟一维前缀和求法相同,这里直接上例子。数组a=[[1,2,2,1],[3,2,2,1],[1,1,1,1]]a数组如图:则数组a的前缀和为:数组b[[1,3,5,6],[4,8,12,14],[5,10,15,18]]b数组如图:前缀和递推公式为b[i][......
  • 前缀和与差分
    前缀和:模版题:https://www.luogu.com.cn/problem/P8218二维前缀和:https://www.luogu.com.cn/problem/P2004前缀和应用:https://www.luogu.com.cn/problem/T430521前缀和应用二:https://www.luogu.com.cn/problem/T430522方法一:计算所有k的前缀和,要点:使用vector,效率nlogn其他......
  • 并查集
    并查集并查集是一种可以动态维护若干个不重叠集合,并且支持合并与查询的数据结构,主要用于处理不相交集合的的合并关系。为了具体实现并查集这种数据结构,首先我们需要定义集合的表示方法。在并查集中,我们采用"代表元"法,即为每一个集合选择一个固定的元素,作为整个集合的代表。其......
  • [算法学习笔记] 差分约束
    Description一个差分约束系统是这样的。给定一组包含\(m\)个不等式,有\(n\)个不等式形如:\[\begin{cases}x_{c_1}-x_{c'_1}\leqy_1\\x_{c_2}-x_{c'_2}\leqy_2\\\cdots\\x_{c_m}-x_{c'_m}\leqy_m\end{cases}\]求任意一组可行解。Solution观察这个式子:\(x_{c1}-......
  • 并查集
    模板题:https://www.luogu.com.cn/problem/P1551题解:#include<bits/stdc++.h>usingnamespacestd;intn,m,p;intfa[5050];intfind(intx){returnfa[x]==x?x:fa[x]=find(fa[x]);}intquery(intx,inty){intfx=find(x),fy=fi......
  • 并查集
    并查集是一种可以动态维护若干个不重叠的集合,并支持合并与查询的数据结构。例:P1551亲戚题目描述:如果\(x\)和\(y\)是亲戚,\(y\)和\(z\)是亲戚,那么\(x\)和\(z\)也是亲戚。如果\(x\)和\(y\)是亲戚,那么\(x\)的亲戚都是\(y\)的亲戚,\(y\)的亲戚也都是\(x\)的......
  • 二分答案&前缀和&差分&离散化(简记)
    二分答案基本codeintFind(intl,intr){ intans,mid; while(l<=r) { intmid=l+r>>1; if(Check(mid))ans=mid,r=mid-1;//舍弃右半部分 elsel=mid+1;//舍弃左半部分 } returnans;}前缀和基本code#inlcude<bits/stdc++.h>usingnamespacestd;intsum[100......
  • 蓝桥杯算法集训 - Week1:二分、前缀和、差分算法
    蓝桥杯算法集训-Week1本系列随笔用于整理AcWing题单——《蓝桥杯集训·每日一题2024》的系列题型及其对应的算法模板。一、二分查找二分算法原理复习参考:二分查找-Hello算法Ⅰ、二分模板boolcheck(intx){/*...*/}//检查x是否满足某种性质//区间[l,r]被划分......
  • 多因素方差分析
    多因素方差分析SPSS统计分析:多因素方差分析-数学中国方差分析-F检验根据因变量的数目,分为:一元多因素方差分析;多元多因素方差分析;方差分析AnalysisOfVariance,ANOVA单因素方差分析说明$y_i=\sum_{j=1}^{n}y_{ij}$—第$i$个水平(处理)观测值总和;$\bar{y}{i.}=y......