E-Explorer_2019牛客暑期多校训练营(第八场)
题意
n个点,m条边,u,v,l,r表示点u到点v有一条边,且只有编号为\([l,r]\)的人能通过,问从点1到点n有哪些编号的人能通过
题解
先对\(l,r\)离散化,用第七场找中位数那题同样的形式建树,每个叶子节点表示的都是一个区间,树上每个节点维护的是,包含这个区间的边有哪些,可以用vector存下来,接着是查询哪些叶子节点可以作为答案,像线段树build一样左右一直递归下去,每递归一次都把这个节点存的边用并查集合并,思考一下就能知道,按build的方式递归下去,到叶子节点x,一定能途径所有包含叶子节点x所表示的区间的边,且不会途径不包含x表示的区间的边,这样到叶子节点是就把包含该叶子节点区间的边全部合并,此时查询点1和点n是否在一起,若在一起就可以把该叶子节点区间计入答案,查询的时候每层递归结束都要撤销并查集合并操作,以免影响递归其他叶子节点的时候影响答案,用启发式并查集合并就能撤销了
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mx = 2e5+5;
vector <int> vv;
vector <int> edge[mx<<2];
int u[mx], v[mx], l[mx], r[mx], fa[mx], sz[mx], top = 0;
int n, m;
pair <int, int> st[mx];
int getid(int x) {
return lower_bound(vv.begin(), vv.end(), x) - vv.begin() + 1;
}
int find(int x) {
return fa[x] == x ? x : find(fa[x]);
}
void merge(int u, int v) {
int fau = find(u);
int fav = find(v);
if (fau == fav) return;
if (sz[fau] > sz[fav]) swap(fau, fav);
fa[fau] = fav;
st[top++] = {fau, sz[fau]};
if (sz[fau] == sz[fav]) {
st[top++] = {fav, sz[fav]};
sz[fav]++;
}
}
void update(int L, int R, int id, int l, int r, int rt) {
if (L <= l && r <= R) {
edge[rt].push_back(id);
return;
}
int mid = (l + r) / 2;
if (L <= mid) update(L, R, id, l, mid, rt<<1);
if (mid < R) update(L, R, id, mid+1, r, rt<<1|1);
}
void cancel(int pre) {
while (top > pre) {
fa[st[top-1].first] = st[top-1].first;
sz[st[top-1].first] = st[top-1].second;
top--;
}
}
void query(int l, int r, int rt, int &ans) {
int pre = top;
for (int i = 0; i < edge[rt].size(); i++) {
int id = edge[rt][i];
merge(u[id], v[id]);
}
if (l == r) {
if (find(1) == find(n)) ans += vv[r]-vv[l-1];
cancel(pre);
return;
}
int mid = (l + r) / 2;
query(l, mid, rt<<1, ans);
query(mid+1, r, rt<<1|1, ans);
cancel(pre);
}
int main() {
for (int i = 0; i < mx; i++) {
fa[i] = i;
sz[i] = 1;
}
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]);
r[i]++;
vv.push_back(l[i]);
vv.push_back(r[i]);
}
sort(vv.begin(), vv.end());
vv.push_back(vv[vv.size()-1] + 1);
vv.erase(unique(vv.begin(), vv.end()), vv.end());
for (int i = 1; i <= m; i++) {
update(getid(l[i]), getid(r[i])-1, i, 1, vv.size()-1, 1);
}
int ans = 0;
query(1, vv.size()-1, 1, ans);
printf("%d\n", ans);
return 0;
}
E-Explorer_2019牛客暑期多校训练营(第八场)的更多相关文章
- 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)
题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9: 对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可. 后者mod=1e9,5才 ...
- 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)
链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...
- 2019牛客暑期多校训练营(第一场) B Integration (数学)
链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...
- 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)
链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...
- 2019牛客暑期多校训练营(第二场)F.Partition problem
链接:https://ac.nowcoder.com/acm/contest/882/F来源:牛客网 Given 2N people, you need to assign each of them ...
- 2019牛客暑期多校训练营(第一场)A Equivalent Prefixes(单调栈/二分+分治)
链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 Two arrays u and v each with m distinct elements ...
- [状态压缩,折半搜索] 2019牛客暑期多校训练营(第九场)Knapsack Cryptosystem
链接:https://ac.nowcoder.com/acm/contest/889/D来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言52428 ...
- 2019牛客暑期多校训练营(第二场)J-Subarray(思维)
>传送门< 前言 这题我前前后后看了三遍,每次都是把网上相关的博客和通过代码认真看了再思考,然并卵,最后终于第三遍也就是现在终于看懂了,其实懂了之后发现其实没有那么难,但是的的确确需要思维 ...
- J-Subarray_2019牛客暑期多校训练营(第二场)
题意 有一个只由1,-1组成的数组,给出所有连续的1所在位置,求满足1的个数大于-1的个数的子区间的数量 题解 参考博客:https://www.cnblogs.com/Yinku/p/1122149 ...
- 2019牛客暑期多校训练营(第一场)-A (单调栈)
题目链接:https://ac.nowcoder.com/acm/contest/881/A 题意:给定两个长度均为n的数组a和b,求最大的p使得(a1,ap)和(b1,bp)等价,等价的定义为其任意 ...
随机推荐
- java并发笔记之synchronized 偏向锁 轻量级锁 重量级锁证明
警告⚠️:本文耗时很长,先做好心理准备 本篇将从hotspot源码(64 bits)入手,通过分析java对象头引申出锁的状态:本文采用大量实例及分析,请耐心看完,谢谢 先来看一下hotspot的 ...
- bootstrap开发响应式网页的常用的一些 类的说明
1.navbar-导航条 1.navbar-fixed-top,让导航条固定显示在页面上部(注意:固定的导航条会遮住代码,解决方案,给body设置padding-top的值[大于或等于]为我们导航条的 ...
- 【Python-Django】浏览器同源策略
1995年,同源政策由 Netscape 公司引入浏览器.目前,所有浏览器都实行这个政策. 同源策略是浏览器的一个安全功能,不同源的客户端脚本(js文件)在没有明确授权的情况下,不能读写对方资源.只有 ...
- Chrome浏览器F12开发者工具简单使用
1.如何调出开发者工具 按F12调出 右键检查(或快捷键Ctrl+Shift+i)调出 2.开发者工具初步介绍 chrome开发者工具最常用的四个功能模块:元素(ELements).控制台(Conso ...
- Thinkphp5.0快速入门笔记(2)
学习来源与说明 https://www.kancloud.cn/thinkphp/thinkphp5_quickstart 测试与部署均在windows10下进行学习. 示例建立新的模块和控制器 在a ...
- Tomcat 单(多)实例部署使用
一.前言 (一).概述 Tomcat 是由 Apache 开发的一个 Servlet 容器,实现了对 Servlet 和 JSP 的支持,并提供了作为Web服务器的一些特有功能,如Tomcat管理和控 ...
- React Native-安卓环境的搭建
最近公司做一个项目,项目中使用React Native(简称RN)来写安卓APP,现在我分享下安卓环境搭建的过程. 我参照https://reactnative.cn/docs/getting-sta ...
- ssh的执行流畅
SSH运行流程 1. 服务器启动,创建Struts2的Filter控制器,创建Spring容器对象. 实例化Struts2控制器时,加载struts.xml,struts-default.xml,de ...
- 8.12 day31 进程间通信 Queue队列使用 生产者消费者模型 线程理论 创建及对象属性方法 线程互斥锁 守护线程
进程补充 进程通信 要想实现进程间通信,可以用管道或者队列 队列比管道更好用(队列自带管道和锁) 管道和队列的共同特点:数据只有一份,取完就没了 无法重复获取用一份数据 队列特点:先进先出 堆栈特点: ...
- size命令的sysv和berkeley格式差别
size命令使用说明 size命令用于显示二进制文件的段(节)大小,其功能类似于readelf -S,详细的说明如下: 用法:size [选项] [文件] 显示二进制文件中节的大小 没有给出输入文件, ...