题意

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牛客暑期多校训练营(第八场)的更多相关文章

  1. 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)

    题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9:  对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可.     后者mod=1e9,5才 ...

  2. 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...

  3. 2019牛客暑期多校训练营(第一场) B Integration (数学)

    链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...

  4. 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)

    链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...

  5. 2019牛客暑期多校训练营(第二场)F.Partition problem

    链接:https://ac.nowcoder.com/acm/contest/882/F来源:牛客网 Given 2N people, you need to assign each of them ...

  6. 2019牛客暑期多校训练营(第一场)A Equivalent Prefixes(单调栈/二分+分治)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 Two arrays u and v each with m distinct elements ...

  7. [状态压缩,折半搜索] 2019牛客暑期多校训练营(第九场)Knapsack Cryptosystem

    链接:https://ac.nowcoder.com/acm/contest/889/D来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言52428 ...

  8. 2019牛客暑期多校训练营(第二场)J-Subarray(思维)

    >传送门< 前言 这题我前前后后看了三遍,每次都是把网上相关的博客和通过代码认真看了再思考,然并卵,最后终于第三遍也就是现在终于看懂了,其实懂了之后发现其实没有那么难,但是的的确确需要思维 ...

  9. J-Subarray_2019牛客暑期多校训练营(第二场)

    题意 有一个只由1,-1组成的数组,给出所有连续的1所在位置,求满足1的个数大于-1的个数的子区间的数量 题解 参考博客:https://www.cnblogs.com/Yinku/p/1122149 ...

  10. 2019牛客暑期多校训练营(第一场)-A (单调栈)

    题目链接:https://ac.nowcoder.com/acm/contest/881/A 题意:给定两个长度均为n的数组a和b,求最大的p使得(a1,ap)和(b1,bp)等价,等价的定义为其任意 ...

随机推荐

  1. 关于java飞机躲炮弹的一些对象说明(带源码)

    1.飞机躲炮弹的各种实体类都需要一个画笔将他们画出来 (GameObject) import java.awt.*; public void drawSelf(Graphics g){ g.drawI ...

  2. Android通过辅助功能实现抢微信红包原理简单介绍

    简书文章:https://www.jianshu.com/p/e1099a94b979 附抢红包开源项目地址,代码已全改为Kotlin了,已适配到最新微信7.0.5版本,如果对你有所帮助赏个star吧 ...

  3. 一道看似简单的go程序的深入分析

    先上代码: func main() { var a [10]int for i := 0; i < 10; i++ { go func(i int) { for { a[i]++ } }(i) ...

  4. div 环形排列

    javascript-按圆形排列DIV元素(一)---- 分析 效果图: 一.分析图: 绿色边框内:外层的DIV元素,相对定位; 白色圆形框:辅助分析的想象形状; 白点:为白色圆形的圆心点,中心点,点 ...

  5. dubbo文档笔记

    配置覆盖关系 以 timeout 为例,显示了配置的查找顺序,其它 retries, loadbalance, actives 等类似: 方法级优先,接口级次之,全局配置再次之. 如果级别一样,则消费 ...

  6. 夯实Java基础(十)——抽象类和接口

    转载自:http://cmsblogs.com/ 该博主的网站上干货非常!非常!非常多(说三遍),强烈推荐大家前去学习. 接口和内部类为我们提供了一种将接口与实现分离的更加结构化的方法 抽象类与接口是 ...

  7. Spring1

    一.Spring是什么?有什么用? Spring的适用环境是这样的,假设现在有一个类port,它将提供一个返回消息的功能,代码如下: public class port { private weibo ...

  8. Redis——基础使用

    Redis总体介绍: Redis特性 Redis(REmote DIctionary Server),是一个开源的内存数据库 持久化:RDB.AOF 主备复制 丰富的数据结构 Lua脚本.事务 Red ...

  9. Java Web基础面试题整理

    Tomcat的缺省端口是多少,怎么修改 tomcat默认缺省端口是8080 修改方法: 找到Tomcat目录下的conf文件夹 进入conf文件夹里面找到server.xml文件 打开server.x ...

  10. 调用链系列(3):如何从零开始捕获body和header

    拓展阅读:调用链系列(1):解读UAVStack中的贪吃蛇 调用链系列(2):轻调用链实现 在Java中,HTTP协议的请求/响应模型是由Servlet规范+Servlet容器(如Tomcat)实现的 ...