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

题目描述

\(DZY\)开始有 \(n\) 个点,现在他对这 \(n\) 个点进行了 \(m\) 次操作,对于第 \(i\) 个操作(从 \(1\)开始编号)有可能的三种情况:

\(Add\ a\ b:\) 表示在 \(a\) 与 \(b\) 之间连了一条长度为 \(i\)的边(注意,\(i\)是操作编号)。保证 \(1≤a,b≤n\)。

\(Delete\ k:\) 表示删除了当前图中边权最大的\(k\)条边。保证$ k$一定不会比当前图中边的条数多。

\(Return\): 表示撤销第 \(i−1\)次操作。保证第 \(1\) 次操作不是 \(Return\) 且第 \(i−1\)次不是 Return 操作。

请你在每次操作后告诉\(DZY\)当前图的最小生成树边权和。如果最小生成树不存在则输出 \(0\)。

输入格式

第一行两个正整数 \(n,m\)。表示有 \(n\) 个点 $m $个操作。 接下来 \(m\)行每行描述一个操作。

输出格式

对于每一个操作输出一行一个整数表示当前最小生成树边权和。

样例一

input

2 2

Add 1 2

Return

output

1

0

样例二

input

5 10

Add 2 1

Add 3 2

Add 4 2

Add 5 2

Add 2 3

Return

Delete 1

Add 2 3

Add 5 2

Return

output

0

0

0

10

10

10

0

0

15

0

样例三

见样例数据下载

限制与约定

测试点编号 n m 其他
\(1、2、3\) \(n≤10^3\) \(m≤10^3\) 只有\(Add\)操作
\(4\) \(n≤2×10^5\) \(m≤2×10^5\) 只有\(Add\)操作
\(5\) \(n≤3×10^5\) \(m≤5×10^5\)
\(6\) \(n≤2×10^5\) \(m≤2×10^5\) 没有\(Return\)操作
\(7\) \(n≤3×10^5\) \(m≤5×10^5\)
\(8\) \(n≤2×10^5\) \(m≤2×10^5\)
\(9、10\) \(n≤3×10^5\) \(m≤5×10^5\)

时间限制:\(1s\)

空间限制:\(64MB\)

分析

我们认真分析题目的话,不难得出以下结论

\(1\)、此题的空间限制较小,如果用可持久化数据 结构很可能会超空间

\(2\)、边权是从小到大加入的,因此如果之前加的边已经可以生成一棵树,那么之后加的边不会产生影响

\(3\)、题目中没有要求强制在线,而且有\(Return\)操作,可以考虑离线

对于\(Add\)操作,我们可以像最小生成树用并查集维护

如果当前的两个节点已经处于一个联通块,那么它们之间的权值一定小于新加入的权值,我们不去管他

如果两个节点属于一个联通块,我们就把两个节点并在一起

对于\(Delete\)操作,路径压缩并查集是无法解决的,因为它会打乱原来的结果,所以我们要用到按秩合并的并查集

所谓按秩合并,就是把深度小的并到深度大的上面或者是把子树小的并到子树大的上面

对于\(Return\)操作,因为是离线处理,所以就好办多了

如果撤销加边操作的话,我们把撤销操作改为删边操作即可

如果撤销删除操作,我们就不去删边,而是用一个\(ans\)数组去记录有\(k\)条边时的最小生成树的权值

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
typedef long long ll;//不开long long见祖宗
inline ll read(){
register ll x=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1LL)+(x<<3LL)+(ch^48);
ch=getchar();
}
return x*f;
}//快读卡常
struct asd{
char jls[3];
ll jla,jlb;
}b[maxn];//离线用结构体
ll fa[maxn],rk[maxn],shuyu[maxn],sta[maxn],top;
ll ans[maxn],n,m,tot,cnt,anscnt;
//fa:并查集父亲节点,rk:子树大小,shuyu:记录某条边属于哪一个节点,sta:存储使用过的边
//ans:记录边数为k时最小生成树的权值和,tot:记录最小生成树的权值,cnt:记录最小生成树的边数,anscnt:记录统计过的答案的个数
ll zhao(ll xx){
if(xx==fa[xx]) return xx;
return zhao(fa[xx]);
}//找到祖先节点
void bing(ll xx,ll yy,ll w){
ll aa=zhao(xx),bb=zhao(yy);
if(aa==bb){
shuyu[w]=-1;
return;
}
if(rk[aa]<rk[bb]) swap(aa,bb);
rk[aa]+=rk[bb];
fa[bb]=aa;
shuyu[w]=bb;
tot+=w,cnt++;
}//按秩合并
void shanchu(ll val){
ll xx=shuyu[val];
ll yy=fa[xx];
rk[yy]-=rk[xx];
fa[xx]=xx;
cnt--,tot-=val;
}//删边
int main(){
n=read(),m=read();
for(ll i=1;i<=n;i++){
fa[i]=i,rk[i]=1;
}
for(ll i=1;i<=m;i++){
scanf("%s",b[i].jls);
if(b[i].jls[0]=='A'){
b[i].jla=read(),b[i].jlb=read();
} else if(b[i].jls[0]=='D'){
b[i].jla=read();
}
}
//初始化+读入
for(ll i=1;i<=m;i++){
if(b[i].jls[0]=='A'){
bing(b[i].jla,b[i].jlb,i);
sta[++top]=i;
if(cnt<n-1) ans[++anscnt]=0;
else ans[++anscnt]=tot;
if(b[i+1].jls[0]=='R'){
b[i+1].jls[0]='D';
b[i+1].jla=1;
}
printf("%lld\n",ans[anscnt]);
} else if(b[i].jls[0]=='D'){
if(b[i+1].jls[0]=='R'){
printf("%lld\n%lld\n",ans[anscnt-b[i].jla],ans[anscnt]);
continue;
}
while(b[i].jla--){
ll now=sta[top--];
anscnt--;
if(shuyu[now]!=-1){
shanchu(now);
}
}
if(cnt<n-1) ans[anscnt]=0;
else ans[anscnt]=tot;
printf("%lld\n",ans[anscnt]);
}
}
return 0;
}

学长小清新题表之UOJ 14.DZY Loves Graph的更多相关文章

  1. 学长小清新题表之UOJ 180.实验室外的攻防战

    学长小清新题表之UOJ 180.实验室外的攻防战 题目描述 时针指向午夜十二点,约定的日子--\(2\)月\(28\)日终于到来了.随着一声枪响,伏特跳蚤国王率领着他的跳蚤大军们包围了 \(picks ...

  2. 学长小清新题表之UOJ 31.猪猪侠再战括号序列

    学长小清新题表之UOJ 31.猪猪侠再战括号序列 题目描述 大家好我是来自百度贴吧的_叫我猪猪侠,英文名叫\(\_CallMeGGBond\). 我不曾上过大学,但这不影响我对离散数学.复杂性分析等领 ...

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

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

  4. uoj problem 14 DZY Loves Graph

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

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

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

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

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

  7. 2019.01.22 uoj#14. 【UER #1】DZY Loves Graph(并查集)

    传送门 题意简述: 要求支持以下操作: 在a与b之间连一条长度为i的边(i是操作编号):删除当前图中边权最大的k条边:表示撤销第 i−1次操作,保证第1次,第i−1 次不是撤回操作. 要求在每次操作后 ...

  8. 【思维题 线段树】cf446C. DZY Loves Fibonacci Numbers

    我这种maintain写法好zz.考试时获得了40pts的RE好成绩 In mathematical terms, the sequence Fn of Fibonacci numbers is de ...

  9. 【Luogu3676】小清新数据结构题(动态点分治)

    [Luogu3676]小清新数据结构题(动态点分治) 题面 洛谷 题解 先扯远点,这题我第一次看的时候觉得是一个树链剖分+线段树维护. 做法大概是这样: 我们先以任意一个点为根,把当前点看成是一棵有根 ...

随机推荐

  1. Linux内核功能介绍及如何使用保护您的网页安全

    在本文中,我们快速浏览了Linux内核的许可流程,并向您展示了如何使用它们来保护您的网页或应用安全 传统上,Linux内核通过以下两类来区分其进程: 特权进程:这些进程使用户可以绕过所有内核权限检查. ...

  2. 题解 洛谷 P6640 【[BJOI2020] 封印】

    设\(lenth_i\)为\(s\)在\(i\)位置的前缀的后缀为\(t\)的一个子串的最长长度,即为从\(i\)位置开始往前和\(t\)的最长公共子串长度.其可以通过对\(t\)建后缀自动机,然后让 ...

  3. 2.pandas的数据结构

    对于文件来说,读取只是最初级的要求,那我们要对文件进行数据分析,首先就应该要知道,pandas会将我们熟悉的文件转换成了什么形式的数据结构,以便于后续的操作 数据结构 pandas对文件一共有两种数据 ...

  4. java排序方式对比

    尽量使用使用Comparator进行排序, 在java中,要想给数据进行排序,有两种事项方式, 一种为实现Comparable接口, 一种是实现Comparator接口, public interfa ...

  5. [转载]android网络通信解析

    原文地址:android网络通信解析作者:clunyes 网络编程的目的就是直接戒间接地通过网络协议不其他计算机进行通讯. 网络编程中有两个主要的问题, 一个是如何准确的定位网络上一台戒多台指主机: ...

  6. Salt组件(二)

    四.配置管理States 是SaltStack中的配置语言,在日常进行配置管理时需要编写大量的States文件.比如我们需要安装一个包,然后管理一个配置文件,最后保证某个服务正常运行.这里就需要我们编 ...

  7. c++输出左右对齐设置

    #include<iostream> int main(){ using std::cout; cout.setf(std::ios::left); int w = cout.width( ...

  8. 在Linux系统中使用Vim读写远程文件

    大家好,我是良许. 今天我们讨论一个 Vim 使用技巧--用 Vim 读写远程文件.要实现这个目的,我们需要使用到一个叫 netrw.vim 的插件.从 Vim 7.x 开始,netrw.vim 就被 ...

  9. PHP curl_share_setopt函数

    (PHP 5 >= 5.5.0) curl_share_setopt — 设置 cURL 共享句柄的一个选项. 说明 bool curl_share_setopt ( resource $sh ...

  10. CF R 630 div2 1332 F Independent Set

    LINK:Independent Set 题目定义了 独立集和边诱导子图.然而和题目没有多少关系. 给出一棵树 求\(\sum_{E'\neq \varnothing,E'\subset E}w(G( ...