首先将边按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. AI 人工智能 探索 (四)

    在写之前,先对昨天寻路插件再做一些补充,因为该插件不是很完善,所以当我发现有不能满足需求的时候,就会试图更改源代码,或增加接口来符合我的需求. 昨天补充了一条是 自身转向代码,今天补充另外一条,是及时 ...

  2. cocos2d-js 帧序列动画

    1.resource.js var res = { playerWalk_plist:"res/playerWalk.plist", playerWalk_png:"re ...

  3. android ScrollView嵌套EditText

    editext.setOnTouchListener(new OnTouchListener() {                        @Override            publi ...

  4. Chapter 1 First Sight——15

    The red-haired woman looked up. "Can I help you?" 红头发的女人抬头看了一眼说,有什么我能帮助你的吗? "I'm Isab ...

  5. windows下spark开发环境配置

    http://www.cnblogs.com/davidwang456/p/5032766.html windows下spark开发环境配置 --本篇随笔由同事葛同学提供. windows下spark ...

  6. 手机端android/iPhone问题

    iPhone: 不能自动播放音乐, 去除默认样式 input:-webkit-appearance: none;border-radius:0px; video播放自动默认全屏解决-webkit-pl ...

  7. do{...}while(0)的妙用(转)

    源:http://www.cnblogs.com/lizhenghn/p/3674430.html 在学习第一门编程语言时,就已经介绍了顺序分支.条件分支.循环分支.比如循环分支有for.while. ...

  8. jQuery获取Select选中的Text和Value,根据Value值动态添加属性等

    语法解释:1. $("#select_id").change(function(){//code...});   //为Select添加事件,当选择其中一项时触发2. var ch ...

  9. css一些特别效果设定

    在CSS中,BOX的Padding属性的数值赋予顺序为 padding:10px; 四个内边距都是10pxpadding:5px 10px; 上下5px 左右10pxpadding:5px 10px ...

  10. CharSequence的getText()与String的getString()(转)

    CharSequence的getText()与String的getString()『Android系列七』 曾经在学习中碰见两种获取常量的方式: CharSequence chrs = getText ...