传送门

题意简述:

要求支持以下操作:

在a与b之间连一条长度为i的边(i是操作编号);删除当前图中边权最大的k条边;表示撤销第 i−1次操作,保证第1次,第i−1 次不是撤回操作。

要求在每次操作后输出当前图的最小生成树边权和。


思路:由于边权为当前操作编号因此相当于边是单调加入的,也就是说我们可以直接上kruskalkruskalkruskal的合并方法。

关键在于怎么维护这几个操作。

加边操作:加入一条边。

删除操作:删掉最近加入的kkk条边。

撤回加边操作:删掉最近加入的一条边

撤回删除操作:等于没有变化。

那么我们用栈存下每一个状态的值转移给后面的状态即可。

注意并查集要简单可持久化一下,可以用按秩合并。

实测了一波按sizesizesize合并比按深度合并快。

按sizesizesize合并代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
typedef long long ll;
const int N=5e5+5;
int n,m,fa[N],siz[N],cnt[N],stk[N],top=0;
ll ans[N];
inline int find(int x){return x==fa[x]?x:find(fa[x]);}
inline void print(int x){cout<<(cnt[x]==n-1?ans[x]:0)<<'\n';}
inline void add(int x,int y,int w){
	int fx=find(x),fy=find(y);
	++top,cnt[top]=cnt[top-1],ans[top]=ans[top-1];
	if(fx==fy)stk[top]=0;
	else{
		if(siz[fx]<siz[fy])swap(fx,fy);
		stk[top]=fy,fa[fy]=fx,siz[fx]+=siz[fy],++cnt[top],ans[top]+=w;
	}
}
inline void delet(int tim){
	while(tim--){
		int p=stk[top--];
		siz[fa[p]]-=siz[p],fa[p]=p;
	}
}
int main(){
	n=read(),m=read();
	for(ri i=1;i<=n;++i)fa[i]=i,siz[i]=1;
	for(ri last=0,k,i=1;i<=m;++i){
		char s[6];
		scanf("%s",s);
		if(s[0]=='A'){
			if(last==2)delet(k);
			int a=read(),b=read();
			add(a,b,i),print(top),last=1;
		}
		else if(s[0]=='D'){
			if(last==2)delet(k);
			int a=read();
			print(top-a),last=2,k=a;
		}
		else{
			if(last==1)delet(1);
			print(top),last=0;
		}
	}
	return 0;
}

按深度合并代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
typedef long long ll;
const int N=3e5+5,M=5e5+5;
int n,m,fa[N],rk[N],cnt[M],stk[M],top=0;
ll ans[M];
inline int find(int x){return x==fa[x]?x:find(fa[x]);}
inline void print(int x){cout<<(cnt[x]==n-1?ans[x]:0)<<'\n';}
inline void add(int x,int y,int w){
	int fx=find(x),fy=find(y);
	++top,cnt[top]=cnt[top-1],ans[top]=ans[top-1];
	if(fx==fy)stk[top]=0;
	else{
		if(rk[fx]<rk[fy])swap(fx,fy);
		stk[top]=fy,fa[fy]=fx,rk[fx]+=rk[fx]==rk[fy],++cnt[top],ans[top]+=w;
	}
}
inline void delet(int tim){
	while(tim--){
		int p=stk[top--];
		rk[fa[p]]-=rk[fa[p]]==rk[p]+1,fa[p]=p;
	}
}
int main(){
	n=read(),m=read();
	for(ri i=1;i<=n;++i)fa[i]=i,rk[i]=1;
	for(ri last=0,k,i=1;i<=m;++i){
		char s[6];
		scanf("%s",s);
		if(s[0]=='A'){
			if(last==2)delet(k);
			int a=read(),b=read();
			add(a,b,i),print(top),last=1;
		}
		else if(s[0]=='D'){
			if(last==2)delet(k);
			int a=read();
			print(top-a),last=2,k=a;
		}
		else{
			if(last==1)delet(1);
			print(top),last=0;
		}
	}
	return 0;
}

2019.01.22 uoj#14. 【UER #1】DZY Loves Graph(并查集)的更多相关文章

  1. UOJ14 DZY Loves Graph 并查集

    传送门 题意:给出一张$N$个点,最开始没有边的图,$M$次操作,操作为加入边(边权为当前的操作编号).删除前$K$大边.撤销前一次操作,每一次操作后询问最小生成树边权和.$N \leq 3 \tim ...

  2. UOJ_14_【UER #1】DZY Loves Graph_并查集

    UOJ_14_[UER #1]DZY Loves Graph_并查集 题面:http://uoj.ac/problem/14 考虑只有前两个操作怎么做. 每次删除一定是从后往前删,并且被删的边如果不是 ...

  3. [UER #1] DZY Loves Graph

    题目描述 开始有 \(n\) 个点,现在对这 \(n\) 个点进行了 \(m\) 次操作,对于第 \(i\) 个操作(从 \(1\) 开始编号)有可能的三种情况: \(Add\) a b: 表示在 \ ...

  4. UOJ14 UER #1 DZY Loves Graph(最小生成树+并查集)

    显然可以用可持久化并查集实现.考虑更简单的做法.如果没有撤销操作,用带撤销并查集暴力模拟即可,复杂度显然可以均摊.加上撤销操作,删除操作的复杂度不再能均摊,但注意到我们在删除时就可以知道他会不会被撤销 ...

  5. cf444E. DZY Loves Planting(并查集)

    题意 题目链接 Sol 神仙题啊Orzzzzzz 考场上的时候直接把树扔了对着式子想,想1h都没得到啥有用的结论. 然后cf正解居然是网络流??出给NOIP模拟赛T1???¥%--&((--% ...

  6. 【UER #1】[UOJ#12]猜数 [UOJ#13]跳蚤OS [UOJ#14]DZY Loves Graph

    [UOJ#12][UER #1]猜数 试题描述 这一天,小Y.小D.小C正在愉快地玩耍. 小Y是个数学家,他一拍脑袋冒出了一个神奇的完全平方数 n. 小D是个机灵鬼,很快从小Y嘴里套出了 n的值.然后 ...

  7. 学长小清新题表之UOJ 14.DZY Loves Graph

    学长小清新题表之UOJ 14.DZY Loves Graph 题目描述 \(DZY\)开始有 \(n\) 个点,现在他对这 \(n\) 个点进行了 \(m\) 次操作,对于第 \(i\) 个操作(从 ...

  8. 【UOJ #14】【UER #1】DZY Loves Graph

    http://uoj.ac/problem/14 题解很好的~ 不带路径压缩的并查集能保留树的原本形态. 按秩合并并查集可以不用路径压缩,但是因为此题要删除,如果把深度当为秩的话不好更新秩的值,所以把 ...

  9. uoj #14.【UER #1】DZY Loves Graph

    http://uoj.ac/problem/14 由于加入的边权递增,可以直接运行kruskal并支持撤销,但这样如果反复批量删边和撤销,时间复杂度会退化,因此需要对删边操作加上延时处理,只有在删边后 ...

随机推荐

  1. 对arm裸板调试的理解

    由于arm芯片一般都包含的由jtag调试这项功能,cpu向外部发出信号时,一般都要同jtag发送出去,它就像一个路口的交警一样,能够控制车辆的运行,当然在arm中指的是cpu发出的数据和地址,我们在调 ...

  2. js数组排序实用方法集锦

    前言: 据说程序员三个月就能忘记自己写的代码,所以最好是在有空的时候及时做些总结,记录下来,这样后边遇到类似问题的话,就可以直接先查看自己的博客了.写技术博客,对自己是一种总结,对别人,是一种参考. ...

  3. 【git】日志提交规范

    我自己总结的规范: feature: 功能添加bugfix: bug修复change: 调整,比如配置,某些方法替换等optimize: 优化过程doc: 文档变更refactor: 重构,功能不变t ...

  4. linux 备忘录

    1. ps aux|grep 程序 -------->查看当前程序是否运行 ps aux|grep nginx 2. tar -zxvf 压缩包 ---------> 解压缩 tar -z ...

  5. maven library has broken path和pom jar包导入失败

    今天在打开项目的时候,在pom文件添加新的依赖文件发现很多jar都标红,显示不存在,自己查了一上午各种尝试,总结了以下的解决方法. 首先你打开File-Project Structrue-Module ...

  6. vm参数配置的理解

    -denv=dev表示将服务器的级别 设置为开发环境 所有错误的内容都会打印在控制台上 //The-Denv = dev statement creates a system property nam ...

  7. stark组件开发之提取公共视图函数

     路由问题, 已经解决! 然后就是视图函数的问题了: 不想重复写的解决途径就是, python  类的继承了! 写一个基类, 基类定义 增删改查. 然后其他的,全部去继承他! from django. ...

  8. power designer 从sqlserver数据库获取字段说明&导出rtf文档模板

    具体的操作稍后在修改 附件下载:https://files.cnblogs.com/files/zinan/powerDesigner.rar

  9. webpack接上一篇

    html-webpack-plugin 自动生成html文件 安装:npm install html-webpack-plugin --save-dev 使用 在webpack.config.js中引 ...

  10. Oracle_PL/SQL(9) 例外处理

    例外处理1.例外分类:预定义例外,非预定义例外,自定义例外三种传递例外:如果在例外处理部分exception没有捕捉例外,oracle会将例外传递到调用环境.捕捉并处理例外:使用例外处理部分完成exc ...