题意

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. python:函数可以返回值--编写脚本计算24 + 34 / 100 - 1023

    1.脚本 def add(a,b):    return (a+b)def div(a,b,c):    return (a/b-c)x = div(34,100,1023)y = add(24,x) ...

  2. jenkins下使用python虚拟环境

    jenkins下使用python虚拟环境碰到的一些坑: 1. 构建使用window批处理 - 坑1 c: cd c:\xxxxx\xxxxx\scripts activate c: cd c:\xxx ...

  3. 小白学python-day08-文件及其操作、字符串字典类型转换

    今天是day08,以下是学习总结: 但行努力,莫问前程. ----------------------------------------------------------------------- ...

  4. hdoj 3732 Ahui Writes Word (多重背包)

    之前在做背包的题目时看到了这道题,一看,大喜,这不是裸裸的01背包吗!!  然后华丽丽的超时,相信很多人也和我一样没有考虑到数据量的大小. 时隔多日,回过头来看这道题,依旧毫无头绪....不过相比之前 ...

  5. UE4 坐标系 坐标轴旋转轴

    Pitch是围绕Y轴旋转,也叫做俯仰角. Yaw是围绕Z轴旋转,也叫偏航角. Roll是围绕X轴旋转,也叫翻滚角. UE4里,蓝图中的rotation的三个依次为roll,pitch,yaw.C++中 ...

  6. linux下mysql无法看到3306端口监听

    这个问题搞定了,原因是我的my.cnf有话:skip-network注释掉,然后运行netstat -an|grep 3306 就可以看到了

  7. 读JDK源码集合部分

    以前读过一遍JDK源码的集合部分,读完了一段时间后忘了,直到有一次面试简历上还写着读过JDK集合部分的源码,但面试官让我说说,感觉记得不是很清楚了,回答的也模模糊糊的,哎,老了记性越来越差了,所以再回 ...

  8. 基于spring的观察者模式

    简单的说,观察者模式,就类似于 广播站发送广播,和收音机的关系.多个收音机去收听同一个广播频道. 在实际的业务场景中,可以是这样的.创建订单成功后,发布事件.然后减库存.发送短信.调用微信.调用物流服 ...

  9. java并发程序和共享对象实用策略

    java并发程序和共享对象实用策略 在并发程序中使用和共享对象时,可以使用一些实用的策略,包括: 线程封闭 只读共享.共享的只读对象可以由多个线程并发访问,但任何线程都不能修改它.共享的只读对象包括不 ...

  10. 什么是https?http升级为https需要什么?

    一.什么是https? https是一种加密传输协议,网站使用https后可以避免敏感信息被第三方获取.https加密协议=SSL / TLS+http协议,也就是说,在传统的http协议上加上SSL ...