题目链接

传送门

题意

给你一张无向图,每条边\(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题+线段树+可撤销并查集)的更多相关文章

  1. Distance(2019年牛客多校第八场D题+CDQ+树状数组)

    题目链接 传送门 思路 这个题在\(BZOJ\)上有个二维平面的版本(\(BZOJ2716\)天使玩偶),不过是权限题因此就不附带链接了,我也只是在算法进阶指南上看到过,那个题的写法是\(CDQ\), ...

  2. 2019牛客暑期多校训练营(第八场) E 线段树+可撤销并查集

    题目传送门 题意: 给出m条无向边,每条边都有一个$[l,r]$,意思是体积在这个范围内的人才能通过这条边,询问有多少种体积的可能性,能使人从1到n 思路:由于是无向边,1和n的连通性可以用并查集维护 ...

  3. 2019牛客多校第八场 F题 Flowers 计算几何+线段树

    2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...

  4. 2020牛客多校第八场K题

    __int128(例题:2020牛客多校第八场K题) 题意: 有n道菜,第i道菜的利润为\(a_i\),且有\(b_i\)盘.你要按照下列要求给顾客上菜. 1.每位顾客至少有一道菜 2.给顾客上菜时, ...

  5. 2019年牛客多校第四场 B题xor(线段树+线性基交)

    题目链接 传送门 题意 给你\(n\)个基底,求\([l,r]\)内的每个基底是否都能异或出\(x\). 思路 线性基交板子题,但是一直没看懂咋求,先偷一份咖啡鸡板子写篇博客吧~ 线性基交学习博客:传 ...

  6. Palindrome Mouse(2019年牛客多校第六场C题+回文树+树状数组)

    目录 题目链接 题意 思路 代码 题目链接 传送门 题意 问\(s\)串中所有本质不同的回文子串中有多少对回文子串满足\(a\)是\(b\)的子串. 思路 参考代码:传送门 本质不同的回文子串肯定是要 ...

  7. generator 1(2019年牛客多校第五场B题+十进制矩阵快速幂)

    目录 题目链接 思路 代码 题目链接 传送门 思路 十进制矩阵快速幂. 代码 #include <set> #include <map> #include <deque& ...

  8. Find the median(2019年牛客多校第七场E题+左闭右开线段树)

    题目链接 传送门 题意 每次往集合里面添加一段连续区间的数,然后询问当前集合内的中位数. 思路 思路很好想,但是卡内存. 当时写的动态开点线段树没卡过去,赛后机房大佬用动态开点过了,\(tql\). ...

  9. 2019年牛客多校第三场 F题Planting Trees(单调队列)

    题目链接 传送门 题意 给你一个\(n\times n\)的矩形,要你求出一个面积最大的矩形使得这个矩形内的最大值减最小值小于等于\(M\). 思路 单调队列滚动窗口. 比赛的时候我的想法是先枚举长度 ...

随机推荐

  1. 基于ZYNQ 的UART中断实验之串口写数据到DDR3中

    1.参考 UG585 网络笔记 2.理论知识 参见上一次实验:基于ZYNQ 的UART中断实验 3.实验目的 练习使用UART的中断实验,并将接收到的数据写入到DDR3中. 4.实验过程 建立工程,设 ...

  2. kali 更改图标村大小

    1.“设置” --> "通用辅助功能" --> "大号字体" 2.在终端中输入 “gnome-tweaks” 打开 优化 --> 扩展  -- ...

  3. spring Valid @Pattern 常见的验证表达式

    1 匹配首尾空格的正则表达式:(^\s*)|(\s*$)   2 整数或者小数:^[0-9]+\.{0,1}[0-9]{0,2}$ 3 只能输入数字:"^[0-9]*$". 4 只 ...

  4. uniapp销毁addEventListener事件

    百度了很多vue的方法,结果都不适用,只好自己想办法,也是无关紧要的东西,不影响运行,但是看着心里都烦,有更好的解决方案欢迎指点上报错信息 这是一个监听滚动的方法,离开了那个页面进入详情页发现这个没有 ...

  5. 报错 xxx@1.0.0 dev D:\> webpack-dev-server --inline --progress --configbuild/webpack.dev.conf.js

    是因为node_modules有意外改动,导致依赖库不完整. 解决:1.删除项目下的node_modules,在你的项目目录下 重新执行npm install,这会重新生成node_modules, ...

  6. python实现Huffman编码

    一.问题 利用二叉树的结构对Huffman树进行编码,实现最短编码 二.解决 # 构建节点类 class TreeNode: def __init__(self, data): "" ...

  7. -Shell 教程 Bash 脚本 基础语法 MD

    目录 目录 Shell 简介 Shell 脚本 Shell 环境 第一个shell脚本 Shell 变量 定义变量 使用变量 只读变量 删除变量 Shell 字符串 单引号 双引号 字符串基本操作 S ...

  8. 通过静态发现方式部署 Etcd 集群

    在「etcd使用入门」一文中对etcd的基本知识点和安装做了一个简要的介绍,这次我们来说说如何部署一个etcd集群. etcd构建自身高可用集群主要有三种形式: 静态发现: 预先已知etcd集群中有哪 ...

  9. 【mysql】mysql5.7支持的json字段查询【mybatis】

    mysql5.7支持的json字段查询 参考:https://www.cnblogs.com/ooo0/p/9309277.html 参考:https://www.cnblogs.com/pfdltu ...

  10. Java静态变量初始化的坑

    class SingleTon { private static SingleTon singleTon = new SingleTon(); public static int count1; pu ...