先说一下题目大意:给定一些线段,这些线段顺序编号,这时候如果两条线段相交,则把他们加入到一个集合中,问给定一个线段序号,求在此集合中有多少条线段. 这个题的难度在于怎么判断线段相交,判断玩相交之后就是怎么找个他们之间的联系,这时候就要用到并查集了. 步骤: 1.判断两条线段相交 2. 用并查集实现查找线段个数和添加到集合中 关于这个判断线段相交的问题.我搞了一晚上加上一下午,刚开始自己想了一种数学上的相交,就是先求出两条线段所在的线性方程,然后求出他们的交点,最后在判断这个交点在不在这两个线段之…
Codeforces 938G Shortest Path Queries 一张连通图,三种操作 1.给x和y之间加上边权为d的边,保证不会产生重边 2.删除x和y之间的边,保证此边之前存在 3.询问x到y的路径异或最小值 保证图在任意时刻连通 首先连通图路径异或相当于从x到y的任意一条路径再异或上若干个环得到的,只要在dfs过程中把非树边成的环丢到线性基里就好了,其他环一定可以通过这些环异或组合出来 有加边删边操作怎么做呢?线段树时间分治!注意到不能保证在线段树的任意一个节点图是连通的,需要用…
线段树(区间修改,区间和): #include <cstdio> #include <iostream> #include <cstring> using namespace std; ],n,m; char s; void update(int p,int l,int r,int x,int add) { ; if (l==r) { c[p]+=add; return; } ,l,m,x,add); +,m+,r,x,add); c[p]=c[p<<]+c…
Description Input Output Sample Input 4 5 1 2 2 3 3 4 4 1 2 4 3 1 5 2 2 3 2 1 2 Sample Output Connected Disconnected Connected HINT N<=100000 M<=200000 K<=100000 Solution 线段树分治,根据询问把每条边存在的时间区间拆成几个区间,然后覆盖到线段树上,最后$DFS$一遍线段树.用带撤销的并查集维护一下连通块个数,到线段树叶子…
https://www.lydsy.com/JudgeOnline/problem.php?id=2049 线段树真神奇 题意:给出一波操作,拆边加边以及询问两点是否联通. 听说常规方法是在线LCT,留坑. 如果说这个删边的操作是删除上一条边,那这自然是可撤销并查集的模板题,直接在线维护就可以了. 但是问题在于删除边的顺序是不可能固定的,要知道并查集是不可以随意撤销的. 万万没想到还有更加高妙的手法. 首先可以证明一条边的存在一定是一段或者多段连续的区间. 建立一条时间节点长度的线段树,结点维护…
Extending Set of Points 我们能发现, 如果把x轴y轴看成点, 那么答案就是在各个连通块里面的x轴的个数乘以y轴的个数之和. 然后就变成了一个并查集的问题, 但是这个题目里面有撤销的操作, 所以我们要把加入和撤销操作变成 这个点影响(L , R)之间的询问, 然后把它丢到线段树里面分成log段, 然后我们dfs一遍线段树, 用按秩合并并查集取维护, 回溯的时候将并查集撤销. #include<bits/stdc++.h> #define LL long long #def…
昨天晚上本来想认真打一场的,,结果陪女朋友去了.. 回来之后看了看D,感觉有点思路,结果一直到现在才做出来 首先对所有线段按左端点排序,然后用并查集判所有边是否联通,即遍历每条边i,和前一条不覆盖它的边合并,和后一条不被它覆盖的边合并 再用线段树求边的总条数 ps.其实可以直接用并查集合并的思路,每个点往前往后连边,建图然后DFS判环/联通就可以了 #include<bits/stdc++.h> #include<set> using namespace std; #define…
传送门 解题思路 可以离线,然后确定每个边的出现时间,算这个排序即可.然后就可以线段树分治了,连通性用并查集维护,因为要撤销,所以要按秩合并,时间复杂度\(O(nlog^2 n)\) 代码 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> using namespace s…
题意: 传送门 有\(n\)个点构成一个无向图,每条边有\(L_i,R_i\)表示这条边只能允许编号为\(L_i\dots R_i\)的人通过,现在问你最多有几个人能从\(1\)走到\(n\). 思路: 我们可以枚举每个编号,然后看看能通过这个编号的所有边能否构成一个图使得\(1\)走到\(n\),但是显然枚举点很不现实,那我们就枚举区间. 我们用左开右闭的线段树维护区间,然后让每个节点保存能覆盖当前区间的边的编号,然后遍历这个线段树.用可撤回的并查集维护当前的图,如果\(1\)和\(n\)在同…
可以利用并查集或者带颜色标记的BFS(来自算法导论)判断. 首先介绍第一种,用并查集来判断: 首先初始化所有元素的根为-1,-1代表根节点,接下来对于图中的每一条边(v1,v2)都并入集合,并入的方式为查找v1和v2的根节点,然后让v2的根节点作为v1的根节点,查找根节点的过程为:如果当前的结点根为-1,说明这个结点就是根,直接返回,否则再继续查找结点父亲的根,直到找到祖先结点,这里因为只是判断环路,不需要压缩路径: int findSet(int x){ if(Parent[x] == -1)…