【LG3247】[HNOI2016]最小公倍数
【LG3247】[HNOI2016]最小公倍数
题面
题解
50pts
因为拼凑起来的部分分比较多,所以就放一起了。
以下设询问的\(a,b\)为\(A,B\),
复杂度\(O(nm)\)的:将所有\(a\leq A,b\leq B\)的边两端,用并查集并起来,再看一看等于\(A,B\)的是否有端点在集合中即可。
一条链的:拿线段树之类的数据结构维护一下即可。
\(a\)等于\(0\)的:将边的和询问按照\(b\)排序,用\(two\;pointers\)扫一遍丢到并查集中即可。
100pts
首先考虑暴力,每次询问暴力求出所有\(\leq a, \leq b\)的边,然后判断判断两点是否联通,并且联通块内最大值是否合法就可以了。
接下来的\(A\)和\(B\)还是是询问的\(a, b\)。
将所有的边按照\(a\)排序并分块,将所有的询问按照\(b\)排序。
设第\(i\)块的区间是\([l_i, r_i]\),找出所有的\(A \in [a_{l_i}, a_{r_i})\)的询问,然后一个一个处理。
对于第\(j\)个询问,有两种边可以产生贡献,一种是在\([1, i)\)的\(b \leq B_j\)的边,这种边可以用一个指针维护。
还有一种是在第\(i\)块的\(a \leq A_j\),\(b \leq B_j\)的边,这种边最多只有块的大小条,可以暴力加边。
因为每一次加了第二种边之后要撤销这些操作,所以要写一个支持撤销的并查集。
然后,当块的大小为\(\sqrt{m\log_2n}\)时据说最快。
(感谢\(xgzc\)友情提供)
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-')
w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
const int MAX_N = 2e5 + 5;
struct Edge { int u, v, a, b; } e[MAX_N];
struct Query { int u, v, a, b, id; } q[MAX_N], p[MAX_N];
struct Node { int u, v, a, b, s; } stk[MAX_N];
bool cmp1(const Edge &l, const Edge &r) { return l.a == r.a ? l.b < r.b : l.a < r.a; }
bool cmp2(const Edge &l, const Edge &r) { return l.b == r.b ? l.a < r.a : l.b < r.b; }
bool cmp3(const Query &l, const Query &r) { return l.b == r.b ? l.a < r.a : l.b < r.b; }
int N, M, Q, top, ans[MAX_N], fa[MAX_N], A[MAX_N], B[MAX_N], size[MAX_N];
int getf(int x) { return fa[x] == x ? x : getf(fa[x]); }
void merge(int x, int y, int a, int b) {
x = getf(x), y = getf(y);
if (size[x] > size[y]) swap(x, y);
stk[++top] = (Node){x, y, A[y], B[y], size[y]};
if (x != y)
fa[x] = y, size[y] += size[x], A[y] = max(A[x], A[y]), B[y] = max(B[x], B[y]);
A[y] = max(A[y], a);
B[y] = max(B[y], b);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
#endif
N = gi(), M = gi();
for (int i = 1; i <= M; i++) e[i] = (Edge){gi(), gi(), gi(), gi()};
Q = gi();
for (int i = 1; i <= Q; i++) q[i] = (Query){gi(), gi(), gi(), gi(), i};
sort(&e[1], &e[M + 1], cmp1);
sort(&q[1], &q[Q + 1], cmp3);
for (int i = 1, LEN = sqrt(M * log2(N)); i <= M; i += LEN) {
for (int j = 1; j <= N; j++) size[fa[j] = j] = 1, A[j] = B[j] = -1;
int tot = 0;
for (int j = 1; j <= Q; j++)
if (e[i].a <= q[j].a && (i + LEN > M || q[j].a < e[i + LEN].a))
p[++tot] = q[j];
if (!tot) continue;
sort(&e[1], &e[i], cmp2);
for (int j = 1, k = 1; j <= tot; j++) {
while (k < i && e[k].b <= p[j].b) merge(e[k].u, e[k].v, e[k].a, e[k].b), ++k;
top = 0;
for (int l = i; l < i + LEN && l <= M; l++)
if (e[l].a <= p[j].a && e[l].b <= p[j].b)
merge(e[l].u, e[l].v, e[l].a, e[l].b);
int x = getf(p[j].u), y = getf(p[j].v);
ans[p[j].id] = (x == y && A[x] == p[j].a && B[x] == p[j].b);
while (top) {
int x = stk[top].u, y = stk[top].v;
fa[x] = x;
A[y] = stk[top].a, B[y] = stk[top].b, size[y] = stk[top].s;
--top;
}
}
}
for (int i = 1; i <= Q; i++) puts(ans[i] ? "Yes" : "No");
return 0;
}
【LG3247】[HNOI2016]最小公倍数的更多相关文章
- BZOJ 4537: [Hnoi2016]最小公倍数 [偏序关系 分块]
4537: [Hnoi2016]最小公倍数 题意:一张边权无向图,多组询问u和v之间有没有一条a最大为a',b最大为b'的路径(不一定是简单路径) 首先想到暴力做法,题目要求就是判断u和v连通,并查集 ...
- [BZOJ4537][HNOI2016]最小公倍数(分块+并查集)
4537: [Hnoi2016]最小公倍数 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1687 Solved: 607[Submit][Stat ...
- [BZOJ4537][Hnoi2016]最小公倍数 奇怪的分块+可撤销并查集
4537: [Hnoi2016]最小公倍数 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1474 Solved: 521[Submit][Stat ...
- 【BZOJ4537】[Hnoi2016]最小公倍数 分块
[BZOJ4537][Hnoi2016]最小公倍数 Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,…,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在 ...
- 4537: [Hnoi2016]最小公倍数
Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,…,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在有q个询问,每次询问给定四个参数u.v.a和b,请你 ...
- bzoj 4537 HNOI2016 最小公倍数
Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,-,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在有q个询问,每次询问给定四个参数u.v.a和b,请你 ...
- [HNOI2016]最小公倍数
题目描述 给定一张N个顶点M条边的无向图(顶点编号为1,2,...,n),每条边上带有权值.所有权值都可以分解成2a∗3b2^a*3^b2a∗3b 的形式. 现在有q个询问,每次询问给定四个参数u.v ...
- 洛谷P3247 [HNOI2016]最小公倍数 [分块,并查集]
洛谷 思路 显然,为了达到这个最小公倍数,只能走\(a,b\)不是很大的边. 即,当前询问的是\(A,B\),那么我们只能走\(a\leq A,b\leq B\)的边. 然而,为了达到这最小公倍数,又 ...
- [HNOI2016]最小公倍数 (可回退并查集,回滚莫队)
题面 题目链接 题目描述 给定一张 N N N 个顶点 M M M 条边的无向图(顶点编号为 1 , 2 , - , n 1,2,\ldots,n 1,2,-,n),每条边上带有权值.所有权值都可以分 ...
随机推荐
- C#.NET里面抽象类,接口,虚方法
1抽象类 (1) 抽象方法只作声明,而不包含实现,可以看成是没有实现体的虚方法 (2) 抽象类不能被实例化 (3) 抽象类可以但不是必须有抽象属性和抽象方法,但是一旦有了抽象方法,就一定要把这个类声明 ...
- 安卓 USB摄像头 开源库 UVCCamera 教程
https://github.com/saki4510t/UVCCamera UVCCamera 听名字就知道使用UVC( USB VEDIO CLASS) 协议的通用类库.linux原生支持,基本支 ...
- 用block将UIAlertView与UIActionSheet统一起来
用block将UIAlertView与UIActionSheet统一起来 效果 1. 将代理方法的实例对象方法转换成了类方法使用 2. 要注意单例block不要长期持有,用完就释放掉 源码 https ...
- [T-ARA][Apple is A]
歌词来源:http://music.163.com/#/song?id=22704474 달콤달콤해 짜릿짜릿해 [tal-Kom-dal-Ko-mae jja-lid-jja-li-Tae] 반짝반 ...
- Ceph PG介绍及故障状态和修复
1 PG介绍pg的全称是placement group,中文译为放置组,是用于放置object的一个载体,pg的创建是在创建ceph存储池的时候指定的,同时跟指定的副本数也有关系,比如是3副本的则会有 ...
- 【洛谷】【线段树+位运算】P2574 XOR的艺术
[题目描述:] AKN觉得第一题太水了,不屑于写第一题,所以他又玩起了新的游戏.在游戏中,他发现,这个游戏的伤害计算有一个规律,规律如下 1. 拥有一个伤害串为长度为n的01串. 2. 给定一个范围[ ...
- Hadoop学习之路(九)HDFS深入理解
HDFS的优点和缺点 HDFS的优点 1.可构建在廉价机器上 通过多副本提高可靠性,提供了容错和恢复机制 服务器节点的宕机是常态 必须理性对象 2.高容错性 数据自动保存多个副本,副本丢失后,自动 ...
- js如何将时间戳转换为标准时间
function formatDate(date,fmt){ let o = { 'M+' : date.getMonth() +1, //月份 'd+' : date.getDate(), //日 ...
- Robot Framework自动化测试---Selenium API
一.浏览器驱动 通过不同的浏览器执行脚本. Open Browser Htpp://www.xxx.com chrome 浏览器对应的关键字: firefox FireFox ff internete ...
- 《Python核心编程》第二版第五章答案
本人python新手,答案自己做的,如果有问题,欢迎大家评论和讨论! 更新会在本随笔中直接更新. 5-1.整型.讲讲Python普通整型和长整型的区别. Python的标准整形类型是最通用的数字类型. ...