首先将边按a的值分组,每$\sqrt{m}$一组。

  对于每一组,将符合一组a的询问选出来,将这些询问和这一块之前的边(a一定小于这些询问)按b排序,然后交替插入,询问,对于一个询问,在当前块也有可能有满足的边,我们将其加入,考虑后并撤销,由于块大小是$\sqrt{m}$所以复杂度正确。

  注意 : 1.并查集不能路径压缩,否则无法撤销;

2.在筛选一组的询问时,不要让一个询问被考虑多次,也就是说用询问的a小于终点后的那条边的a作为筛选条件,否则假如所有的a一样,那么每个询问每次都会被考虑一遍。

  复杂度为$\sqrt{m}mlog(m) + Q \sqrt{m}$

 #include <bits/stdc++.h>
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define drep(i, a, b) for (int i = a; i >= b; i--)
#define REP(i, a, b) for (int i = a; i < b; i++)
#define pb push_back
#define mp make_pair
#define xx first
#define yy second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
template <typename T> void Max(T& a, T b) { if (b > a) a = b; }
//********************************* const int maxn = , maxm = ;
struct DATA {
int u, v, a, b, id;
} e[maxm], q[maxn], tmp[maxn];
bool cmpa(DATA a, DATA b) { return a.a < b.a; }
bool cmpb(DATA a, DATA b) { return a.b < b.b; } struct Option {
int x, y, xmaxa, xmaxb, sz, ymaxa, ymaxb, f; Option() {}
Option(int _x, int _y, int _xmaxa, int _xmaxb, int _sz, int _ymaxa, int _ymaxb, int _f) :
x(_x), y(_y), xmaxa(_xmaxa), xmaxb(_xmaxb), sz(_sz), ymaxa(_ymaxa), ymaxb(_ymaxb), f(_f) {}
} op[maxn]; int top;
int fa[maxn], sz[maxn], maxa[maxn], maxb[maxn];
int ans[maxn];
int getfather(int x) { return fa[x] == x ? x : getfather(fa[x]); }
void merge(int x, int y, int a, int b) {
int fx = getfather(x), fy = getfather(y);
if (sz[fx] < sz[fy]) swap(fx, fy);
op[++top] = (Option){fx, fy, maxa[fx], maxb[fx], sz[fx], maxa[fy], maxb[fy], fa[fy]};
if (fx == fy) {
maxa[fx] = max(maxa[fx], a);
maxb[fx] = max(maxb[fx], b);
return;
}
sz[fx] += sz[fy];
maxa[fx] = max(maxa[fx], max(maxa[fy], a));
maxb[fx] = max(maxb[fx], max(maxb[fy], b));
fa[fy] = fx;
} void retrace() {
drep(i, top, ) {
maxa[op[i].x] = op[i].xmaxa;
maxb[op[i].x] = op[i].xmaxb;
maxa[op[i].y] = op[i].ymaxa;
maxb[op[i].y] = op[i].ymaxb;
fa[op[i].y] = op[i].f;
sz[op[i].x] = op[i].sz;
}
} int main() {
/*
freopen("multiple.in", "r", stdin);
freopen("multiple.out", "w", stdout);
*/
int n, m; scanf("%d%d", &n, &m);
rep(i, , m) scanf("%d%d%d%d", &e[i].u, &e[i].v, &e[i].a, &e[i].b);
int Q; scanf("%d", &Q);
rep(i, , Q) scanf("%d%d%d%d", &q[i].u, &q[i].v, &q[i].a, &q[i].b), q[i].id = i;
int Sz = sqrt(m); sort(e + , e + + m, cmpa);
sort(q + , q + + Q, cmpb); for (int st = ; st <= m; st += Sz) {
int end = min(st + Sz - , m); int cnt();
for (int i = ; i <= Q; i++) if (q[i].a >= e[st].a && (st + Sz > m || q[i].a < e[end + ].a)) tmp[++cnt] = q[i];
if (!cnt) continue; sort(e + , e + st, cmpb); rep(i, , n) fa[i] = i, sz[i] = , maxa[i] = maxb[i] = -;
for (int k = , j = ; k <= cnt; k++) {
while (e[j].b <= tmp[k].b && j < st) merge(e[j].u, e[j].v, e[j].a, e[j].b), j++; top = ;
rep(i, st, end) if (e[i].a <= tmp[k].a && e[i].b <= tmp[k].b) merge(e[i].u, e[i].v, e[i].a, e[i].b);
int fx = getfather(tmp[k].u), fy = getfather(tmp[k].v);
if (fa[fx] == fa[fy] && maxa[fx] == tmp[k].a && maxb[fx] == tmp[k].b) ans[tmp[k].id] = ;
retrace();
} }
rep(i, , Q) if (ans[i]) puts("Yes"); else puts("No"); return ;
}

multiple

【 bzoj4537】HNOI2016 最小公倍数的更多相关文章

  1. [BZOJ4537][HNOI2016]最小公倍数(分块+并查集)

    4537: [Hnoi2016]最小公倍数 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 1687  Solved: 607[Submit][Stat ...

  2. [BZOJ4537][Hnoi2016]最小公倍数 奇怪的分块+可撤销并查集

    4537: [Hnoi2016]最小公倍数 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 1474  Solved: 521[Submit][Stat ...

  3. BZOJ4537 HNOI2016最小公倍数(莫队+并查集)

    考虑边只有一种权值的简化情况.那么当且仅当两点可以通过边权<=x的边连通,且连通块内最大边权为x时,两点间存在路径max为x的路径.可以发现两种权值是类似的,当且仅当两点可以通过边权1<= ...

  4. BZOJ4537 : [Hnoi2016]最小公倍数

    将边按$a$从小到大排序,每$\sqrt{m}$个取一个关键点. 对于每个关键点,将这个点之前的边以及要在这个关键点回答的询问按$b$排序. 依次加入这个关键点之前的每条边,用并查集维护每个连通块$a ...

  5. 【BZOJ4537】[Hnoi2016]最小公倍数 分块

    [BZOJ4537][Hnoi2016]最小公倍数 Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,…,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在 ...

  6. BZOJ 4537: [Hnoi2016]最小公倍数 [偏序关系 分块]

    4537: [Hnoi2016]最小公倍数 题意:一张边权无向图,多组询问u和v之间有没有一条a最大为a',b最大为b'的路径(不一定是简单路径) 首先想到暴力做法,题目要求就是判断u和v连通,并查集 ...

  7. 【LG3247】[HNOI2016]最小公倍数

    [LG3247][HNOI2016]最小公倍数 题面 洛谷 题解 50pts 因为拼凑起来的部分分比较多,所以就放一起了. 以下设询问的\(a,b\)为\(A,B\), 复杂度\(O(nm)\)的:将 ...

  8. 【bzoj4537】 Hnoi2016—最小公倍数

    http://www.lydsy.com/JudgeOnline/problem.php?id=4537 (题目链接) 题意 给出一个${n}$个点${m}$条边的无向图,每条边有两个权值${a,b} ...

  9. 4537: [Hnoi2016]最小公倍数

    Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,…,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在有q个询问,每次询问给定四个参数u.v.a和b,请你 ...

随机推荐

  1. 在Activity之间使用Intent传值和Bundle传值的区别和方式

    两者本质上没有任何区别.Bundle只是一个信息的载体 将内部的内容以键值对组织 Intent负责Activity之间的交互 自己是带有一个Bundle的Intent.putExtras(Bundle ...

  2. hadoop yarn 易理解

    Hadoop 和 MRv1 简单介绍 Hadoop 集群可从单一节点(其中所有 Hadoop 实体都在同一个节点上运行)扩展到数千个节点(其中的功能分散在各个节点之间,以增加并行处理活动).图 1 演 ...

  3. DHCP详细工作过程(转)

    DHCP客户端通过和DHCP服务器的交互通讯以获得IP地址租约.为了从DHCP服务器获得一个IP地址,在标准情况下DHCP客户端和DHCP服务器之间会进行四次通讯.DHCP协议通讯使用端口UDP 67 ...

  4. (转)Windows管道(Pipe)重定向stdout,stderr,stdin

    参考: http://qiusuoge.com/11496.html http://www.cnblogs.com/BoyXiao/archive/2011/01/01/1923828.html st ...

  5. Telepro工具注册码

    Teleport Pro v1.54 注册码 Teleport Pro v1.54姓名(Name):3ddown.com序列号(Serial):161594593

  6. MyEclipse8.5优化经验

    第一步: 取消自动validation    validation有一堆,什么xml.jsp.jsf.js等等,我们没有必要全部都去自动校验一下,只是需要的时候才会手工校验一下!    取消方法:   ...

  7. storm第一篇--概念,例子,参数优化

    1 概念 目前最新的0.8.0版本里面 worker -> 进程.一个worker只能执行同一个spout/bolt的task,一个worker里面可以有多个executor. executor ...

  8. Linux运维常用的命令详解

    1. 查看系统内核版本 [root@funsion geekxa]# cat /etc/issue CentOS release 6.5 (Final) Kernel \r on an \m 显示了系 ...

  9. C#入门经典(第三章-1)

    #region--------#endregion 此关键字 将设置代码是否可以折叠和展开.但是他们不是C#关键字.注意:带#的是预处理指令,严格说不是C#关键字. 变量:

  10. AngularJS中的$http.post与jQuery.post的区别

    原文:http://my.oschina.net/tommyfok/blog/287748 很多时候我们需要用ajax提交post数据,angularjs与jq类似,也有封装好的post. 但是jQu ...