DZY开始有 nn 个点,现在他对这 nn 个点进行了 mm 次操作,对于第 ii 个操作(从 11 开始编号)有可能的三种情况:

  1. Add a b: 表示在 aa 与 bb 之间连了一条长度为 ii 的边(注意,ii是操作编号)。保证 1≤a,b≤n1≤a,b≤n。
  2. Delete k: 表示删除了当前图中边权最大的k条边。保证 kk 一定不会比当前图中边的条数多。
  3. Return: 表示撤销第 i−1i−1 次操作。保证第 11 次操作不是 Return 且第 i−1i−1 次不是 Return 操作。

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

输入格式

第一行两个正整数 n,mn,m。表示有 nn 个点 mm 个操作。 接下来 mm 行每行描述一个操作。

输入格式

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

样例一

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

样例三

见样例数据下载

正解:并查集+各种奇怪维护

解题报告:

  调试了两个多小时才AC,而且还蒯了别人的题解。

  传送门:http://vfleaking.blog.uoj.ac/blog/15

  我讲不太清楚,直接看vfk的博客吧。

 //It is made by jump~
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#ifdef WIN32
#define OT "%I64d"
#else
#define OT "%lld"
#endif
using namespace std;
typedef long long LL;
const int MAXM = ;
int n,m,cnt;//cnt统计树边
LL ans;
int father[MAXM],last[MAXM];//分别表示最小生成树中的所在块的祖先和这条边断掉之后的所在块的祖先(前提,这条边在最小生成树中)
//int stack[MAXM];
int size[MAXM],top;
char ch[];
LL num[MAXM];
vector<int>q;
struct ask{
int type,x,y;
}Q[MAXM]; inline int getint()
{
int w=,q=;
char c=getchar();
while((c<'' || c>'') && c!='-') c=getchar();
if (c=='-') q=, c=getchar();
while (c>='' && c<='') w=w*+c-'', c=getchar();
return q ? -w : w;
} inline int find(int x){
if(father[x]!=x) return find(father[x]);
return father[x];
} inline void delet(int x){
int u;
while(x--) {
u=q[q.size()-]; q.pop_back();
//u=stack[top]; top--;
if(last[u]!=-) {
ans-=u; cnt--; int y=father[u];
while(y)
{
size[y]-=size[u];
if(y==father[y]) break;
}
//if(father[x]) size[father[x]]-=size[x];
father[last[u]]=last[u];
}
}
} inline void work(){
n=getint(); m=getint();
for(int i=;i<=m;i++) {
scanf("%s",ch);
if(ch[]=='A') Q[i].type=,Q[i].x=getint(),Q[i].y=getint();
else if(ch[]=='D') Q[i].type=,Q[i].x=getint();
else Q[i].type=;
}
for(int i=;i<=n;i++) father[i]=i,size[i]=;
int x,y;
for(int i=;i<=m;i++) {
if(Q[i].type==) {
//stack[++top]=i;
q.push_back(i);
x=find(Q[i].x); y=find(Q[i].y);
if(x!=y) {//加入最小生成树,后面的肯定不如前面的编号小的更优
if(size[x]>size[y]) swap(x,y);//交换,按秩
last[i]=x;
father[x]=y; size[y]+=size[x];
ans+=i; cnt++;
}
else last[i]=-;//不在最小生成树中
}
else if(Q[i].type==) {
if(Q[i+].type==) {
//printf("%lld\n",num[top-Q[i].x]);
printf("%lld\n",num[q.size()-Q[i].x]);
continue;
}else delet(Q[i].x);
}
else {
if(Q[i-].type==) delet();
} if(cnt==n-) {//构成最小生成树
//num[top]=ans;
num[q.size()]=ans;
printf("%lld\n",ans);
}
else {
//num[top]=0;
num[q.size()]=;
printf("0\n"); }
}
} int main()
{
work();
return ;
}

UOJ14 DZY Loves Graph的更多相关文章

  1. UOJ14 DZY Loves Graph 并查集

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

  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.DZY Loves Graph

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

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

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

  5. [UER #1] DZY Loves Graph

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

  6. uoj problem 14 DZY Loves Graph

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

  7. 【UER #1】DZY Loves Graph

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

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

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

  9. 【UER #1】DZY Loves Graph(待卡常数)

    题解: 正解是可持久化并查集 但这个显然是lct可以维护的 但这常数是个问题啊??? #include <bits/stdc++.h> using namespace std; struc ...

随机推荐

  1. TFS二次开发-基线文件管理器(2)-TFS登录

    首先需要做一个TFS的登录. 以前的文章是使用的DomainProjectPicker 最新的VS里面使用的是TeamProjectPicker 首先可以在WinForm程序上写一个Button,然后 ...

  2. 从“关于Java堆与栈的思考”一帖看错误信息的传播

    我对转贴的信息一直有敌意,原因如下:首先,除了制造更多的信息垃圾,转贴不会带来新的价值,想收藏的话一个链接足矣:其次,将错误信息以讹传讹,混淆视听.不妨选一个典型的例子说明一二. 相信<关于Ja ...

  3. a标签里面包含img标签,出现a标签的高度高于img标签好几个px

    问题:a标签里面包含img标签,出现a标签的高度高于img标签好几个px 解决: a元素下有一个匿名文本,这个文本外有一个匿名行级盒子,它有的默认vertical-align是baseline的,而且 ...

  4. python多进程理论

    什么是进程 进程:正在进行的一个过程或者说一个任务.而负责执行任务则是cpu. 举例(单核+多道,实现多个进程的并发执行): 你在一个时间段内有很多任务要做:python学习的任务,赚钱的任务,交女朋 ...

  5. Linux源码包安装和脚本安装

    能够先 vi INSTALL 看看安装过程. 1.源码包安装 2.脚本安装

  6. Servlet 运行原理

    一:servlet定义 Servlet是一个Java应用程序,运行在服务器端,用来处理客户端请求并作出响应的程序. 二:简单servlet实例 //导入所需的包 import javax.servle ...

  7. Maven学习笔记—仓库

    Maven仓库 1 什么是Maven仓库 在Maven中,任何一个依赖.插件或者项目构建的输出,都可以成为构件,而Maven通常在某个位置统一的存储所有Maven项目共享的构件,这个统一的位置就是Ma ...

  8. python并发编程之多线程2---(死锁与递归锁,信号量等)

    一.死锁现象与递归锁 进程也是有死锁的 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用, 它们都将无法推进下去.此时称系统处于死锁状态或系统 ...

  9. web前端基础知识学习网站推介

    内容:一.基础知识及学习资料1. HTML入门学习:http://www.w3school.com.cn/html/index.aspHTML5 入门学习:http://www.w3school.co ...

  10. Adaptive Execution如何让Spark SQL更高效更好用

    1 背  景 Spark SQL / Catalyst 和 CBO 的优化,从查询本身与目标数据的特点的角度尽可能保证了最终生成的执行计划的高效性.但是 执行计划一旦生成,便不可更改,即使执行过程中发 ...