首先将边按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. php cookies自动登录

    <?php header('Content-type: text/html; charset=utf-8'); error_reporting(0); //自动登陆 if($_COOKIE[&q ...

  2. 利用工具MailUtils实现邮件的发送,遇到的大坑,高能预警!!

    java实现邮件的发送依赖的jar包有两个:mail.jar和activation.jar,我也找到了一个工具包:itcast-tools-1.4.jar,实现原理大家可以查看源码,先放出资源链接 h ...

  3. struts体系结构

    问题:   为什么 invoke()方法,一旦执行,表示action方法执行完毕,jsp页面已经处理完毕: 其返回值再修改无意义,不影响结果?? 解释: 着重看如下颜色的字: ■ ■ 官方文档有明确的 ...

  4. Web跨浏览器进程通信(Web跨域)

    Web跨域已是老生常谈的话题,这次来尝试下跨域浏览器进程之间的通信 —— 这在过去基本依靠网络中转实现   在之前一篇文章里尝试了跨浏览器的数据共享,最后提到使用LocalConnection还可以实 ...

  5. Entity Framework 学习中级篇1—EF支持复杂类型的实现

    本节,将介绍如何手动构造复杂类型(ComplexType)以及复杂类型的简单操作. 通常,复杂类型是指那些由几个简单的类型组合而成的类型.比如:一张Customer表,其中有FristName和Las ...

  6. CF 389 E 贪心(第一次遇到这么水的E)

    http://codeforces.com/contest/389/problem/E 这道题目刚开始想的特别麻烦...但是没想到竟然是贪心 我们只需要知道偶数的时候可以对称取的,然后奇数的时候没次取 ...

  7. Segment,Path,Ring和Polyline对象

    Segment几何对象   Segment对象是一个有起点和终点的“线“,也就是说Segement只有两个点,至于两点之间的线是直的,还是曲的,需要其余的参数定义.所以Segment是由起点,终点和参 ...

  8. HDOJ 1319 Prime Cuts<数论>

    学会了不难.通过这道题学习了两点: 1:筛选法求素数. 2:在写比较长的程序的时候,给每个功能部分加上注释,思路会更清晰. 题意: 1.题目中所说的素数并不是真正的素数,包括1: 2.需要读懂题意,对 ...

  9. Win7+QTP10.0+IE9无法识别对象的解决方法

    在WIN7和IE9环境下使用QTP10,会出现识别不了web对象的情况,具体表现为:添加对象,先打开对象库,再打开IE,点击Add object to local 后,出现白色手指,将其拖拉到百度首页 ...

  10. [iOS]C语言技术视频-01-变量的定义

    下载地址: 链接: http://pan.baidu.com/s/1eQJaVwY 密码: c7j8