题目:

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

  • Add a b: 表示在 \(a\) 与 \(b\) 之间连了一条长度为 \(i\) 的边(注意,\(i\)是操作编号)。保证 \(1 \leq a, b \leq n\)。
  • Delete k: 表示删除了当前图中边权最大的k条边。保证 \(k\) 一定不会比当前图中边的条数多。
  • Return: 表示撤销第 \(i-1\) 次操作。保证第 \(1\) 次操作不是 Return 且第 \(i-1\) 次不是 Return 操作。

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

题解:

首先我们来挖掘一下题目的性质.

  1. 加入的边权值递增
  2. 如果一条边被删除,那么所有大于这条边权值的边要么没被加入,要么已经被删除.

    所以我们可以直接大力可持久化并查集.

    \(O(mlog^2n)\) 做一些有理有据的底层优化应该能过掉.

但其实这道题没有那么复杂.

首先我们先忽略掉Return操作.

我们考虑维护动态加入和删除的并查集.

我们可以直接在\(O(mlogn)\)内完成.

但其实加上Return操作后对我们的做法也没有什么影响.

进行每一次操作的时候,我们首先检查一下下一操作是不是Return操作

如果不是Return我们就直接在现有的状态上进行修改.

如果是Return那么我们就计算出当前操作的影响,并不把这份影响加入到我们当前的状态中.

这样我们就可以直接用一维数组解决掉啦..

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch > '!');if(flag) x=-x;
}
const int maxn = 510010;
int fa[maxn],siz[maxn];
inline int find(int x){
while(fa[x] != x) x = fa[x];
return x;
}
int ope[maxn];
char s[12];
struct ope{
int op,u,v;
}op[maxn];
ll ans[maxn],sum[maxn];
int main(){
int n,m;read(n);read(m);
for(int i=1;i<=n;++i) fa[i] = i,siz[i] = 1;
for(int i=1;i<=m;++i){
scanf("%s",s);
if(*s == 'A'){
op[i].op = 1;
read(op[i].u);
read(op[i].v);
}else if(*s == 'D'){
op[i].op = 2;
read(op[i].u);
}else if(*s == 'R') op[i].op = 3;
}
int ecnt = 0,nodecnt = n;
for(int i=1;i<=m;++i){
if(op[i].op == 1){
if(op[i+1].op == 3){
if(nodecnt == 1) printf("%lld\n",ans[ecnt]);
else if(nodecnt == 2){
int x = find(op[i].u);
int y = find(op[i].v);
if(x == y) puts("0");
else printf("%lld\n",sum[ecnt] + i);
}else puts("0");
printf("%lld\n",ans[ecnt]);
++ i;
}else{
ans[ecnt+1] = ans[ecnt];
sum[ecnt+1] = sum[ecnt];
++ecnt;
int x = find(op[i].u);
int y = find(op[i].v);
if(x == y){
printf("%lld\n",ans[ecnt]);
ope[ecnt] = 0;
continue;
}
if(siz[x] > siz[y]) swap(x,y);
fa[x] = y;siz[y] += siz[x];ope[ecnt] = x;
sum[ecnt] += i;
if(--nodecnt == 1) ans[ecnt] = sum[ecnt];
printf("%lld\n",ans[ecnt]);
}
}else if(op[i].op == 2){
if(op[i+1].op == 3){
printf("%lld\n",ans[ecnt-op[i].u]);
++ i;
printf("%lld\n",ans[ecnt]);
}else{
for(int j=0;j<op[i].u;++j){
if(ope[ecnt] != 0){
int x = ope[ecnt];
++ nodecnt;
siz[fa[x]] -= siz[x];
fa[x] = x;
}-- ecnt;
}
printf("%lld\n",ans[ecnt]);
}
}
}
return 0;
}

uoj problem 14 DZY Loves Graph的更多相关文章

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

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

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

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

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

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

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

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

  5. Codeforces Round #FF (Div. 2):Problem A - DZY Loves Hash

    A. DZY Loves Hash time limit per test 1 second memory limit per test 256 megabytes input standard in ...

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

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

  7. UOJ14 DZY Loves Graph

    DZY开始有 nn 个点,现在他对这 nn 个点进行了 mm 次操作,对于第 ii 个操作(从 11 开始编号)有可能的三种情况: Add a b: 表示在 aa 与 bb 之间连了一条长度为 ii ...

  8. [UER #1] DZY Loves Graph

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

  9. 【UER #1】DZY Loves Graph

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

随机推荐

  1. Nodejs通过thrift访问Java服务

    上一篇文章中实现了用Java作为thrift客户端和服务端.接下来我们用nodejs作为客户端访问一下.Nodejs的安装可以查看http://www.cnblogs.com/xucheng/p/39 ...

  2. 九度OJ 1349:数字在排序数组中出现的次数 (排序、查找)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2489 解决:742 题目描述: 统计一个数字在排序数组中出现的次数. 输入: 每个测试案例包括两行: 第一行有1个整数n,表示数组的大小. ...

  3. elasticsearch从入门到出门-04-入门的几个需求练手

    第一个分析需求:计算每个tag下的商品数量 GET /ecommerce/product/_search{  "aggs": {    "group_by_tags&qu ...

  4. iOS-事件传递和响应机制

    转自:http://www.jianshu.com/p/2e074db792ba 前言: 按照时间顺序,事件的生命周期是这样的: 事件的产生和传递(事件如何从父控件传递到子控件并寻找到最合适的view ...

  5. Python菜鸟之路:Python基础-生成器和迭代器、递归

    一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,知道所有的元素被访问完结束.迭代器只能往前不会后退. 1. 迭代器优点 对于无法随机访问的数据结构(比如set)而言, ...

  6. SNMP 监控方式的配置

    由于某些设备并不能安装 Agent,或者不方便安装 Agent 等因素,将采用 SNMP 方式进行监控 1.Linux 配置 SNMP [root@crazy-acong ~]# yum -y ins ...

  7. Hadoop初体验(续)--YARN

    1.Hadoop已经安装完成并启动成功 复制mapred-site.xml.template重命名为mapred-site.xml /etc/hadoop/mapred-site.xml.templa ...

  8. 基于PI的Webservice发布实例

    [转自http://blog.csdn.net/yin_chuan_lang/article/details/6706816] 最近的项目中,接口较多,而Webservice技术是主要实现方式之一.下 ...

  9. ABAP xml

    [转]Part 1 - Expressiveness of Simple TransformationsSimple Transformations are a SAP proprietary pro ...

  10. Javaweb基础--->利用监听器统计在线用户数量和用户信息

    首页布局:index.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" ...