题意

有 \(n\) 个点,\(m\) 条边,每条边连接 \(u \Leftrightarrow v\) 且权值为 \((a, b)\) 。

共有 \(q\) 次询问,每次询问给出 \(u, v, q_a, q_b\) 。

问是否存在一个联通块 \(S\) ,使得其中包含 \(u, v\) 且 \(S\) 中的边 \(e\) 满足 \(\max_{e \in S} a_e = q_a, \max_{e \in S} b_e = q_b\) 。

\(n, q \le 5 \times 10^4, m \le 10^5\)

题解

对于这种有两维 \(a, b\) 最大值确定的题,常常可以用分块来解决问题。

具体来说就是先把 \(a\) 从小到大排序,然后分块。

我们把每个询问挂在 \(q_a\) 被第 \(i\) 个块所有的边的 \(a_e\) 构成的区间包含的块中(如果有多个挂在最后一个)。

然后考虑把 \(i\) 之前的所有的边以及当前区间挂的询问按 \(b\) 从小到大排序即可。

然后从前往后一次处理每个操作,如果有边就加入并查集中(并查集维护连通性,以及每个联通块 \(S\) 边权 \(a,b\) 的最大值)。

如果是询问的话,暴力将当前块内合法的边(也就是两维都不超过当前询问)加入即可,然后最后记得需要把所有加入的边撤回。

这个利用可撤销并查集就行了。(按秩(深度)合并,用栈维护维护之前的状态就行了)

似乎把块调成 \(\sqrt {n \log n}\) ,可以做到 \(O(n \sqrt {n \log n})\) 的复杂度。(此处假设 \(n, m\) 同级)复杂度当然是瞎分析的啦qwq

总结

对于求两位偏序需要满足条件的题,常常可以分块然后配合可撤销数据结构来解决。

然后可以调整块大小优化复杂度?

代码

#include <bits/stdc++.h>

#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << (x) << endl
#define DEBUG(...) fprintf(stderr, __VA_ARGS__) using namespace std; template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, T b) { return b > a ? a = b, 1 : 0; } inline int read() {
int x(0), sgn(1); char ch(getchar());
for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1;
for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48);
return x * sgn;
} void File() {
#ifdef zjp_shadow
freopen ("P3247.in", "r", stdin);
freopen ("P3247.out", "w", stdout);
#endif
} const int N = 1e5 + 1e3; struct Option { int u, v, a, b, k; inline void Get(int k_ = 0) {
u = read(); v = read();
a = read(); b = read(); k = k_;
} } E[N], Q[N]; struct Cmpa {
inline bool operator () (const Option &lhs,const Option &rhs) const {
return lhs.a != rhs.a ? lhs.a < rhs.a : lhs.b < rhs.b;
}
}; struct Cmpb {
inline bool operator () (const Option &lhs,const Option &rhs) const {
return lhs.b != rhs.b ? lhs.b < rhs.b : lhs.a < rhs.a;
}
}; int n, m, blk, ans[N]; namespace Union_Set { Option stk[N]; int top; int fa[N], height[N], maxa[N], maxb[N]; int find(int x) { return fa[x] == x ? x : find(fa[x]); } Option Merge(int u, int v, int a, int b) {
u = find(u); v = find(v);
if (height[u] > height[v]) swap(u, v);
Option tmp = (Option) {u, v, maxa[v], maxb[v], height[v]};
if (height[u] == height[v]) ++ height[v]; fa[u] = v;
chkmax(maxa[v], max(a, maxa[u]));
chkmax(maxb[v], max(b, maxb[u])); return tmp;
} void Retract() {
Option cur = stk[top --];
fa[cur.u] = cur.u; maxa[cur.v] = cur.a; maxb[cur.v] = cur.b; height[cur.v] = cur.k;
} } Option ask[N]; int len; int id[N], Mina[N], Maxa[N], bel[N], Beg[N], End[N]; int main () { File(); n = read(); m = read(); blk = (int)(sqrt(n * log2(m))) * 0.6; For (i, 1, m) E[i].Get();
sort(E + 1, E + m + 1, Cmpa()); For (i, 1, m) {
id[i] = i / blk + 1;
if (id[i] != id[i - 1]) {
Mina[id[i]] = Maxa[id[i]] = E[i].a;
Beg[id[i]] = i; End[id[i - 1]] = i - 1;
}
else chkmin(Mina[id[i]], E[i].a), chkmax(Maxa[id[i]], E[i].a);
}
End[id[m]] = m; int q = read();
For (i, 1, q) {
Q[i].Get(i);
Fordown (j, id[m], 1)
if (Mina[j] <= Q[i].a && Q[i].a <= Maxa[j]) { bel[i] = j; break; }
} using namespace Union_Set; For (i, 1, m) if (id[i] != id[i - 1]) { len = 0; For (j, 1, q) if (bel[j] == id[i]) ask[++ len] = Q[j]; if (!len) continue ; sort(E + 1, E + i, Cmpb());
sort(ask + 1, ask + len + 1, Cmpb()); For (j, 1, n) fa[j] = j, maxa[j] = maxb[j] = -1;
int pa = 1, pb = 1;
while (pa < i || pb <= len) {
if ((pa < i && E[pa].b <= ask[pb].b) || pb > len) {
Merge(E[pa].u, E[pa].v, E[pa].a, E[pa].b); ++ pa;
} else {
For (j, Beg[id[i]], End[id[i]])
if (E[j].a <= ask[pb].a && E[j].b <= ask[pb].b)
stk[++ top] = Merge(E[j].u, E[j].v, E[j].a, E[j].b);
int rt = find(ask[pb].u);
if (rt == find(ask[pb].v))
ans[ask[pb].k] = maxa[rt] == ask[pb].a && maxb[rt] == ask[pb].b;
while (top) Retract(); ++ pb;
}
} } For (i, 1, q) puts(ans[i] ? "Yes" : "No"); return 0; }

LOJ #2048. 「HNOI2016」最小公倍数的更多相关文章

  1. 「HNOI2016」最小公倍数 解题报告

    「HNOI2016」最小公倍数 考虑暴力,对每个询问,处理出\(\le a,\le b\)的与询问点在一起的联通块,然后判断是否是一个联通块,且联通块\(a,b\)最大值是否满足要求. 然后很显然需要 ...

  2. loj #2051. 「HNOI2016」序列

    #2051. 「HNOI2016」序列 题目描述 给定长度为 n nn 的序列:a1,a2,⋯,an a_1, a_2, \cdots , a_na​1​​,a​2​​,⋯,a​n​​,记为 a[1: ...

  3. 「HNOI2016」最小公倍数

    链接 loj 一道阔爱的分块 题意 边权是二元组(A, B),每次询问u, v, a, b,求u到v是否存在一条简单路径,使得各边权上\(A_{max} = a, B_{max} = b\) 分析 对 ...

  4. loj2048 「HNOI2016」最小公倍数

    link 题意: 给定一张$N$个顶点$M$条边的无向图(顶点编号为$1,2,...,n$),每条边上带有权值.所有权值都可以分解成$2^a \cdot 3^b$的形式. 现在有$q$个询问,每次询问 ...

  5. loj#2049. 「HNOI2016」网络(set 树剖 暴力)

    题意 题目链接 Sol 下面的代码是\(O(nlog^3n)\)的暴力. 因为从一个点向上只会跳\(logn\)次,所以可以暴力的把未经过的处理出来然后每个点开个multiset维护最大值 #incl ...

  6. LOJ#2052. 「HNOI2016」矿区(平面图转对偶图)

    题面 传送门 题解 总算会平面图转对偶图了-- 首先我们把无向边拆成两条单向边,这样的话每条边都属于一个面.然后把以每一个点为起点的边按极角排序,那么对于一条边\((u,v)\),我们在所有以\(v\ ...

  7. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  8. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

  9. Loj #3093. 「BJOI2019」光线

    Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...

随机推荐

  1. python中*args,**kwargs

     *args :当我们不知道要有多少个参数传给函数,或者我们想把一个列表或者tuple存起来以后传给函数. **kwargs:当我们不知道有多少个关键字参数要传给函数,或者我们想把字典存起来以后传给函 ...

  2. Failure to transfer org.apache.maven:maven-archiver:pom:2.5 from https://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval o

    pom.xml报错: Failure to transfer org.apache.maven:maven-archiver:pom:2.5 from https://repo.maven.apach ...

  3. rem移动端适配方案

    一. rem vs em 单位 定义 特点 rem font size of the root element 以根元素字体大小为基准 em font size of the element 以父元素 ...

  4. 关于spring的源码的理解

    从最基础的Hello World开始. spring的Hello World就三行代码: public void test() { ApplicationContext context = new C ...

  5. python学习笔记(4)-基本数据类型-数字类型及操作

    大学mooc 北京理工大学 python语言程序设计课程学习笔记 一.整数类型 可正可负,没有取值范围的限制(这个与c不同,c要考虑数据类型的存储空间).如pow(x,y),计算x的y次方,pow(2 ...

  6. WPF 如何创建自己的WPF自定义控件库

    在我们平时的项目中,我们经常需要一套自己的自定义控件库,这个特别是在Prism这种框架下面进行开发的时候,每个人都使用一套统一的控件,这样才不会每个人由于界面不统一而造成的整个软件系统千差万别,所以我 ...

  7. SQL Server2012中如何通过bak文件还原SQL Server2012数据库

    1 登陆完数据库后,不要新建数据库,直接点击“数据库”然后右击"还原数据库". 2 在"源"选项中选择"设备". 3 选择相应的bak文件并 ...

  8. Java多线程之通过标识关闭线程

    package org.study2.javabase.ThreadsDemo.status; /** * @Auther:GongXingRui * @Date:2018/9/19 * @Descr ...

  9. 【转】console.log 用法

    标签: 转自http://www.cnblogs.com/ctriphire/p/4116207.html 大家都有用过各种类型的浏览器,每种浏览器都有自己的特色,本人拙见,在我用过的浏览器当中,我是 ...

  10. linux环境 :LIBRARY_PATH, LD_LIBRARY_PATH区别

    参考: https://www.cnblogs.com/mylinux/p/4955448.html LIBRARY_PATH和LD_LIBRARY_PATH是Linux下的两个环境变量,二者的含义和 ...