图论 + 并查集 ----最小生成树重构图 + 可撤销并查集 + set启发式合并 时间线上的离线求解 D. Graph and Queries
解题思路
题目大意:
就是给你一个无向图,每个点都有一个权值,和qqq次询问
每次询问有两种操作
- 1 x:就询问从x点出发,能访问到的最大权值是多少,并把最大权值那个点的权值设置为0
- 2 x:就是删除第xxx条边
解题思考
- 首先我一开始想正着做但是很麻烦
- 我考虑每个要被删除的边,它要是对答案有影响那么它肯定是破环了连通性,我们可以先求个生成树,维护好连通性
- 那么我们先把没有要删除的边先求一个生成树,因为这些边是不会被删除的连通性不会变了,然后把,删除的边,按照逆序,为了方便并查集维护生成树时候撤销
- 我们用setsetset去维护每个块,合并的时候启发式合并就好了
- 这里有个小tiptiptip是就是每次访问过的点就在setsetset里面永久删除,因为它变成0了,永远不可能是答案了
- 那么我们就是对所有点开个setsetset
AC code
#include <bits/stdc++.h>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define LLF 0x3f3f3f3f3f3f3f3f
#define f first
#define s second
#define endl '\n'
using namespace std;
const int N = 2e6 + 10, mod = 1e9 + 9;
const int maxn = 600010;
const long double eps = 1e-5;
const int EPS = 500 * 500;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x) {x = 0;char ch = getchar();ll f = 1;while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args) {read(first);read(args...);
}
int n, m, q;
bool col[maxn];
vector<PII> ask, edge, last;
bool vis[maxn];
int fa[maxn], siz[maxn];
set<PII>stk[maxn];
vector<PII> tmp; int find(int p) {if(p == fa[p]) return p;return find(fa[p]);
}
inline void done(PII v) {int x = find(v.first),y = find(v.second);if(x == y ) {tmp.push_back(make_pair(-1,-1)); return;}if(siz[x] > siz[y]) swap(x,y); tmp.push_back(make_pair(x,y));set<PII>::iterator it = stk[x].begin();// 启发式插入for(;it != stk[x].end(); ++ it) {stk[y].insert(*it);}fa[x] = y; siz[y] += siz[x];
}inline void undone() {PII z = tmp.back(); tmp.pop_back();if(z.first == -1) return; set<PII>::iterator it = stk[z.first].begin();for(;it != stk[z.first].end();) {if(col[(*it).second]) {// 只把永远不会出现的数删掉set<PII>::iterator ittmp = it;it ++;stk[z.first].erase(ittmp);}else {stk[z.second].erase(*it);// 从大集合里面删除it ++;}}fa[z.first] = z.first; siz[z.second] -= siz[z.first];
}int main() {IOS;cin >> n >> m >> q;for(int i = 1; i <= n; ++ i) {int v;cin >> v;stk[i].insert({v,i});}for(int i = 0; i < m; ++ i) {int u, v;cin >> u >> v;edge.push_back({u,v});}for(int i = 0; i < q; ++ i) {int op, v;cin >> op >> v;ask.push_back({op,v});if(op == 2) vis[v-1] = 1, last.push_back(edge[v-1]);}for(int i = 1; i <= n; ++ i) fa[i] = i, siz[i] = 1;for(int i = 0; i < m; ++ i) {if(vis[i]) continue;done(edge[i]);}for(int i = last.size()-1; i >= 0; -- i) done(last[i]);for(int i = 0; i < q; ++ i) {int op = ask[i].first, v = ask[i].second;if(op == 2) undone();else {v = find(v);if(stk[v].empty()) cout << "0\n";else {cout << (*stk[v].rbegin()).first << endl;auto it = *stk[v].rbegin();col[it.second] = 1;stk[v].erase(it);// cout << it.second << " = v " << endl;}}}return 0;
}
图论 + 并查集 ----最小生成树重构图 + 可撤销并查集 + set启发式合并 时间线上的离线求解 D. Graph and Queries相关推荐
- 图论8 并查集深入解析——边带权并查集和拓展域并查集和最小生成树
我们先复习一下并查集的基本知识. 并查集的三个操作:查询,初始化,合并:并查集的结构:操作方法以及代码:路径压缩优化(详见<图论7 弗洛伊德&并查集算法详解>). 补充一下,并查集 ...
- 【挑战程序设计】- 2.5 图论(最短路、最小生成树)
2.5 图论(最短路.最小生成树) 文章目录 2.5 图论(最短路.最小生成树) 2.5.1 定义们 2.5.2 图的表示 2.5.3 图的搜索 2.5.4 最短路问题 单源1:bellman-for ...
- codeforces 892E(离散化+可撤销并查集)
题意 给出一个n个点m条边的无向联通图(n,m<=5e5),有q(q<=5e5)个询问 每个询问询问一个边集{Ei},回答这些边能否在同一个最小生成树中 分析 要知道一个性质,就是权值不同 ...
- 线段树分治 ---- F. Extending Set of Points(线段树分治 + 可撤销并查集)
题目链接 题目大意: 你有个点集合SSS,每次往集合里面加点或者删点(如果要加的点出现过),如果(x1,y1),(x2,y1),(x1,y2),(x2,y2)(x1,y1),(x2,y1),(x1,y ...
- 线段树分治 ---- CF1217F - Forced Online Queries Problem(假离线 可撤销并查集 + 线段树分治)详解
题目链接 题目大意 解题思路: 我一开始想到可以用可撤销并查集去维护这种删边加边的操作,但是有个缺点是每次撤销都有把后面的边全部撤销复度是O(n2)O(n^2)O(n2) 首先我们考虑这种动态加边删边 ...
- 【带你重拾Redis】Redis 哨兵集群实现高可用
Redis 哨兵集群实现高可用 哨兵的介绍 sentinel,中文名是哨兵.哨兵是 Redis 集群架构中非常重要的一个组件,主要有以下功能: 集群监控:负责监控 Redis master 和 sla ...
- 2020CCPC(长春) - Ragdoll(启发式合并+带权并查集)
题目大意:初始时给出 n 个集合,每个集合中都包含有一个数字,现在要求执行 m 次操作,每次操作分为下列三种类型: 1 x y:在 x 位置新建一个集合,并且放置一个数字 y 2 x y:合并集合 x ...
- bzoj 36733674 可持久化并查集加强版(可持久化线段树+启发式合并)
CCZ在2015年8月25日也就是初三暑假要结束的时候就已经能切这种题了%%% 学习了另一种启发式合并的方法,按秩合并,也就是按树的深度合并,实际上是和按树的大小一个道理,但是感觉(至少在这题上)更好 ...
- 洛谷P7518:宝石(倍增、可撤销并查集)
解析 算法一 定义 upx,kup_{x,k}upx,k 为节点 xxx 从自己的颜色所在位置在返祖链上往后跳 2k2^k2k 个颜色到达的节点. 可以像倍增一样的求解. 这样对于一次询问 (s,t ...
最新文章
- POJ1679 Luogu4180 次小生成树
- [OpenGL ES 03]3D变换:模型,视图,投影与Viewport
- 【2018ACM山东省赛 - E】Sequence(树状数组,思维,优化)
- 20sccm_SCCM 2012安装图解教程(一步一步详细步骤)
- 机器人合金礼包_《Apex英雄》福利twitch礼包领取详细攻略,1机器人皮肤+5个包!...
- WordPress 主题教程 #5:主循环
- egg前面加什么,egg前加a还是an?
- Magic Odd Square 思维
- DEM高程数据下载方法
- 超详细|开关电源电路图及原理讲解
- 关于zblog模板当中标签、相关文章调用应该怎么来写
- 刘宇凡:一棵树给我的真理
- RGB(三色)灯配置常用颜色数据,用法讲解,基于C语言的程序讲解,七彩渐变程序讲解
- 微信公众平台版面设计需要服务器,微信公众平台丨排版的基本原则
- Spring Boot多模块项目打包
- 肖战真的没我帅!我自己写的Python颜值检测说的!
- JS 中 replace 和 replaceAll 的区别?
- python文件打包成之pyinstaller使用
- 地理坐标系_GCS汇总
- 【环境问题】Anaconda-Navigator 更新后无法打开,运行出现UnicodeDecodeError的解决方案