题目链接
题意
给定n个带权结点,给定一些联通关系,然后给出q条命令,分为以下两种
- 查询和x相连的所有节点中,权值比x权值大,且权值最大的点,若有多个输出编号最小的
- 拆除x-y的连边
思路
多敲几道并查集就能一眼看出是带权并查集了,用value数组维护所在集合中最大权值点的id。关键在于拆边,我们知道并查集是无法进行撤销操作的(如果能的话当我没说……^ ^)。但好在这题只需要进行拆除操作,那么我们完全可以离线操作,将命令从后往前执行,提前建好没被拆除的边,将拆除看作建边,依次回答询问即可。如果嫌看代码麻烦的话我这里点几个坑点,自查一下:
- N,M,Q范围分别是1w,2w,5w,存的时候别手滑全按小的存的(应该不止我一个人错吧~~)
- 多组样例,每组输出后打印空白行,而且最后一组输出不要空白行
- 拆的边和给的边顺序可能不一样。比如给你边的时候是5 7,拆的时候可能是7 5,不处理会wa
代码
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
#define int long long
using namespace std;
//typedef long long ll;
const int maxn=10500,maxm=20500,maxq=50500;
const int inf=0x3f3f3f3f;
int n,m,q;
int fa[maxn],va[maxn],p_va[maxn];//父节点,并查集权(存集合中最大点权的id),点权
int ans[maxq];//用于倒序输出
void init(){
for(int i=0;i<maxn;i++){
fa[i]=i;
va[i]=i;
}
}
int find(int x){
if(fa[x]==x)
return x;
int t=find(fa[x]);
if(p_va[va[fa[x]