Explorer(2019年牛客多校第八场E题+线段树+可撤销并查集)
题目链接
题意
给你一张无向图,每条边\(u_i,v_i\)的权值范围为\([L_i,R_i]\),要经过这条边的条件是你的容量要在\([L_i,R_i]\),现在问你你有多少种容量使得你可以从\(1\)走到\(n\)。
思路
跟着大佬们的代码学了波可撤销并查集和线段树骚操作,感觉自己好菜啊。
首先我们用并查集来维护哪些边的权值范围在线段树结点对应的区间内,用\(vector\)来存下结点编号(注意由于区间范围太大我们需要离散化建左闭右开线段树)。在查询的时候一路向下,将经过的结点存的所有边的编号对应的两个端点用并查集维护连通性,当到达线段树叶子结点时就说明所有包含这个叶子结点对应的区间的边都用并查集维护了,此时再判断\(1\)与\(n\)是否在一个连通块里面,在就将这个区间的长度加到答案里面,不在就说明这个结点对应的区间无法使得从\(1\)走到\(n\),在回溯的时候撤销之前并查集的合并集合操作。
代码
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson (rt<<1),L,mid
#define rson (rt<<1|1),mid + 1,R
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("/home/dillonh/CLionProjects/Dillonh/in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 200000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
pii st[maxn*4];
int n, m, tot, tp, ans;
vector<int> vec[maxn*4];
int u[maxn], v[maxn], L[maxn], R[maxn];
int num[maxn*2], fa[maxn], sz[maxn];
int fi(int x) {
return fa[x] == x ? x : fi(fa[x]);
}
void merge(int u, int v) {
int x = fi(u), y = fi(v);
if(x == y) {
st[++tp] = {-1, -1}; //按照我的写法不能省略,因为我是根据结点对应的vector的size来撤消的,少了这个那么tp会减到负数导致re。
return;
}
if(sz[x] < sz[y]) swap(x, y);
sz[x] += sz[y];
fa[y] = x;
st[++tp] = {x, y};
}
void cancel() {
int x = st[tp].first;
int y = st[tp--].second;
if(x == -1) return;
sz[x] -= sz[y];
fa[y] = y;
}
void update(int l, int r, int id, int rt, int L, int R) {
if(l <= L && R <= r) {
vec[rt].emplace_back(id);
return;
}
int mid = (L + R) >> 1;
if(r <= mid) update(l, r, id, lson);
else if(l > mid) update(l, r, id, rson);
else {
update(l, mid, id, lson);
update(mid + 1, r, id, rson);
}
}
void query(int l, int r, int rt) {
for(int i = 0; i < (int)vec[rt].size(); ++i) {
int id = vec[rt][i];
merge(u[id], v[id]);
}
if(l == r) {
int x = fi(1), y = fi(n);
if(x == y) {
ans += num[r+1] - num[l];
}
for(int i = 0; i < (int)vec[rt].size(); ++i) {
cancel();
}
return;
}
int mid = (l + r) >> 1;
query(l, mid, rt<<1);
query(mid + 1, r, rt<<1|1);
for(int i = 0; i < (int)vec[rt].size(); ++i) {
cancel();
}
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; ++i) {
scanf("%d%d%d%d", &u[i], &v[i], &L[i], &R[i]);
num[++tot] = L[i];
num[++tot] = R[i] + 1;
}
sort(num + 1, num + tot + 1);
tot = unique(num + 1, num + tot + 1) - num - 1;
for(int i = 1; i <= m; ++i) {
int l = lower_bound(num + 1, num + tot + 1, L[i]) - num;
int r = lower_bound(num + 1, num + tot + 1, R[i] + 1) - num;
update(l, r - 1, i, 1, 1, tot);
}
for(int i = 1; i <= n; ++i) fa[i] = i, sz[i] = 1;
query(1, tot, 1);
printf("%d\n", ans);
return 0;
}
Explorer(2019年牛客多校第八场E题+线段树+可撤销并查集)的更多相关文章
- Distance(2019年牛客多校第八场D题+CDQ+树状数组)
题目链接 传送门 思路 这个题在\(BZOJ\)上有个二维平面的版本(\(BZOJ2716\)天使玩偶),不过是权限题因此就不附带链接了,我也只是在算法进阶指南上看到过,那个题的写法是\(CDQ\), ...
- 2019牛客暑期多校训练营(第八场) E 线段树+可撤销并查集
题目传送门 题意: 给出m条无向边,每条边都有一个$[l,r]$,意思是体积在这个范围内的人才能通过这条边,询问有多少种体积的可能性,能使人从1到n 思路:由于是无向边,1和n的连通性可以用并查集维护 ...
- 2019牛客多校第八场 F题 Flowers 计算几何+线段树
2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...
- 2020牛客多校第八场K题
__int128(例题:2020牛客多校第八场K题) 题意: 有n道菜,第i道菜的利润为\(a_i\),且有\(b_i\)盘.你要按照下列要求给顾客上菜. 1.每位顾客至少有一道菜 2.给顾客上菜时, ...
- 2019年牛客多校第四场 B题xor(线段树+线性基交)
题目链接 传送门 题意 给你\(n\)个基底,求\([l,r]\)内的每个基底是否都能异或出\(x\). 思路 线性基交板子题,但是一直没看懂咋求,先偷一份咖啡鸡板子写篇博客吧~ 线性基交学习博客:传 ...
- Palindrome Mouse(2019年牛客多校第六场C题+回文树+树状数组)
目录 题目链接 题意 思路 代码 题目链接 传送门 题意 问\(s\)串中所有本质不同的回文子串中有多少对回文子串满足\(a\)是\(b\)的子串. 思路 参考代码:传送门 本质不同的回文子串肯定是要 ...
- generator 1(2019年牛客多校第五场B题+十进制矩阵快速幂)
目录 题目链接 思路 代码 题目链接 传送门 思路 十进制矩阵快速幂. 代码 #include <set> #include <map> #include <deque& ...
- Find the median(2019年牛客多校第七场E题+左闭右开线段树)
题目链接 传送门 题意 每次往集合里面添加一段连续区间的数,然后询问当前集合内的中位数. 思路 思路很好想,但是卡内存. 当时写的动态开点线段树没卡过去,赛后机房大佬用动态开点过了,\(tql\). ...
- 2019年牛客多校第三场 F题Planting Trees(单调队列)
题目链接 传送门 题意 给你一个\(n\times n\)的矩形,要你求出一个面积最大的矩形使得这个矩形内的最大值减最小值小于等于\(M\). 思路 单调队列滚动窗口. 比赛的时候我的想法是先枚举长度 ...
随机推荐
- mysql 主从 数据不一致
用pt-table-checksum校验数据一致性 Jun 4th, 2013 主从数据的一致性校验是个头疼的问题,偶尔被业务投诉主从数据不一致,或者几个从库之间的 数据不一致,这会令人沮丧.通常我们 ...
- 关于“100g文件全是数组,取最大的100个数”解决方法汇总
原题如下: 有一个100G大小的文件里存的全是数字,并且每个数字见用逗号隔开.现在在这一大堆数字中找出100个最大的数出来. 我认为,首先要摸清考官的意图.是想问你os方面的知识,还是算法,或者数据结 ...
- 【Docker】涨姿势,深入了解Dockerfile 中的 COPY 与 ADD 命令
参考资料:https://www.cnblogs.com/sparkdev/p/9573248.html Dockerfile 中提供了两个非常相似的命令 COPY 和 ADD,本文尝试解释这两个命令 ...
- Docker容器内部端口映射到外部宿主机端口 - 运维笔记
Docker允许通过外部访问容器或者容器之间互联的方式来提供网络服务.容器启动之后,容器中可以运行一些网络应用,通过-p或-P参数来指定端口映射. 注意:宿主机的一个端口只能映射到容器内部的某一个端口 ...
- 在电脑上远程连接你的 云服务器( ECS)
在与服务器上一般安装的主流操作系统 linux 和 windowsServer linux一般都是centOs系列 这个主要是连接windowsServer 系统 用xshell ,win ...
- Ubuntu18 安装搭建Harbor
1.安装docker-compose1.下载docker-compose的最新版本 sudo curl -L "https://github.com/docker/compose/relea ...
- Maven安装及配置(Linux系统)
环境说明:Linux环境,CentOS 7版本. 第一步:下载Maven,地址:http://maven.apache.org/download.cgi 我这里下载的是[apache-maven-3. ...
- linux 1-常用命令
文件处理命令: 命令格式:命令 [-选项] [参数] 例如:ls -la /etc 多个选项可以写在一起,不区分前后关系,例如 -l 和 -a 一起写成 -la 目录处理命令:ls (就是list ...
- 基于 DNS 动态发现方式部署 Etcd 集群
使用discovery的方式来搭建etcd集群方式有两种:etcd discovery和DNS discovery.在 「基于已有集群动态发现方式部署etcd集群」一文中讲解了etcd discove ...
- c# 创建Excel com加载项Ribbon动态加载工作簿和工作表
使用 VSTO 创建外接程序,Gallery控件动态加载工作簿名称 代码如下: 加载工作簿名称: private void Gallery1_ItemsLoading(object sender, R ...