2019.01.22 uoj#14. 【UER #1】DZY Loves Graph(并查集)
传送门
题意简述:
要求支持以下操作:
在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(并查集)的更多相关文章
- UOJ14 DZY Loves Graph 并查集
传送门 题意:给出一张$N$个点,最开始没有边的图,$M$次操作,操作为加入边(边权为当前的操作编号).删除前$K$大边.撤销前一次操作,每一次操作后询问最小生成树边权和.$N \leq 3 \tim ...
- UOJ_14_【UER #1】DZY Loves Graph_并查集
UOJ_14_[UER #1]DZY Loves Graph_并查集 题面:http://uoj.ac/problem/14 考虑只有前两个操作怎么做. 每次删除一定是从后往前删,并且被删的边如果不是 ...
- [UER #1] DZY Loves Graph
题目描述 开始有 \(n\) 个点,现在对这 \(n\) 个点进行了 \(m\) 次操作,对于第 \(i\) 个操作(从 \(1\) 开始编号)有可能的三种情况: \(Add\) a b: 表示在 \ ...
- UOJ14 UER #1 DZY Loves Graph(最小生成树+并查集)
显然可以用可持久化并查集实现.考虑更简单的做法.如果没有撤销操作,用带撤销并查集暴力模拟即可,复杂度显然可以均摊.加上撤销操作,删除操作的复杂度不再能均摊,但注意到我们在删除时就可以知道他会不会被撤销 ...
- cf444E. DZY Loves Planting(并查集)
题意 题目链接 Sol 神仙题啊Orzzzzzz 考场上的时候直接把树扔了对着式子想,想1h都没得到啥有用的结论. 然后cf正解居然是网络流??出给NOIP模拟赛T1???¥%--&((--% ...
- 【UER #1】[UOJ#12]猜数 [UOJ#13]跳蚤OS [UOJ#14]DZY Loves Graph
[UOJ#12][UER #1]猜数 试题描述 这一天,小Y.小D.小C正在愉快地玩耍. 小Y是个数学家,他一拍脑袋冒出了一个神奇的完全平方数 n. 小D是个机灵鬼,很快从小Y嘴里套出了 n的值.然后 ...
- 学长小清新题表之UOJ 14.DZY Loves Graph
学长小清新题表之UOJ 14.DZY Loves Graph 题目描述 \(DZY\)开始有 \(n\) 个点,现在他对这 \(n\) 个点进行了 \(m\) 次操作,对于第 \(i\) 个操作(从 ...
- 【UOJ #14】【UER #1】DZY Loves Graph
http://uoj.ac/problem/14 题解很好的~ 不带路径压缩的并查集能保留树的原本形态. 按秩合并并查集可以不用路径压缩,但是因为此题要删除,如果把深度当为秩的话不好更新秩的值,所以把 ...
- uoj #14.【UER #1】DZY Loves Graph
http://uoj.ac/problem/14 由于加入的边权递增,可以直接运行kruskal并支持撤销,但这样如果反复批量删边和撤销,时间复杂度会退化,因此需要对删边操作加上延时处理,只有在删边后 ...
随机推荐
- DRF的权限和频率
DRF的权限 权限组件源码 权限和频率以及版本认证都是在initial方法里初始化的 我们的权限类一定要有has_permission方法~否则就会抛出异常~~这也是框架给我提供的钩子~~ 在rest ...
- Android 各个版本新特性
一.Android 4.x 新锁屏界面: Android4.0重新设计了锁屏幕UI,下方的解锁虚拟按键向周围发射出微光,轻轻拖动就可以解锁,比原来在UI上确实有很大的进步. 全新Widget排列: 主 ...
- h5外部浏览器直接调起app
1. 安卓端: 其中,scheme必须是小写的,同时要求H5必须是“<a href="appback://">启动应用程序</a> ” 2. h5端完整示例 ...
- 论equals与==不同的重要性
首先借鉴一下CSDN前辈的总结: 在编程中,通常比较两个字符串是否相同的表达式是“==” ,但在 Java 中不能这么写.在 Java 中,如果要比较 a 字符串是否等于 b 字符串,需要这么写: i ...
- Delphi异步编程:匿名线程与匿名方法
异步编程,是项目中非常有用的而且常用的一种方法,大多以线程实现. 而Delphi传统方法使用线程略为烦琐,好在其后续版本中,提供一些方法,简化一些操作. 几个概念: 匿名线程:TAnonymousTh ...
- docker-ce-17.09 容器创建,运行,进入,删除,导入/导出
docker容器是镜像运行的一个运行实例,带有额外的可写文件层. 一.创建容器 > docker create -it centos:latest create命令新建的容器处于停止状态,可以使 ...
- gearman管理工具GearmanManager的安装与使用
一.gearman自带了一个gearadmin工具 查看帮助信息 > gearadmin --help 查看状态 > gearadmin --status 查看worker信息 > ...
- [Z]sql优化
前言:平常写的SQL可能主要以实现查询出结果为主,但如果数据量一大,就会突出SQL查询语句优化的性能独特之处.一般的数据库设计都会建索引查询,这样较全盘扫描查询的确快了不少.下面总结下SQL查询语句的 ...
- Oracle性能优化1-总体思路和误区
最近在看梁敬彬老师关于Oracle性能优化的一些案例,在这里做一些简单的总结 1.COUNT(*)与COUNT(列)哪个更快 drop table t purge; create table t as ...
- web服务器 双网卡 路由 设置
最近在装服务器的时候,遇到一个问题,就是这个服务器本身是一个web服务器,但它上面装有一个局域网数据交换软件,还需要访局域网. 但软件装上去了,局域网怎么也不能访问,后来了解到是因为双网卡的原因,需要 ...