首先将边按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. 解决TortoiseGit 推送 拉取需要密码的问题

    找到解决了方法: 1)运行PuTTYGen,在Conversions菜单中点击Import key,选择ssh-keygen生成的私钥文件所在位置,比如id_rsa文件. 2)点击Save priva ...

  2. ReactiveCocoa & FRP & MVVM

    Functional Reactive Programming(以下简称FRP)是一种响应变化的编程范式.先来看一小段代码 a = 2 b = 2 c = a + b // c is 4 b = 3 ...

  3. 关于js向jsp中传输中文乱码问题

    最近做项目遇到的js向jsp中传中文结果是乱码,不知道是否是我换了用eclipse的原因还是什么,以前用的MyEclipse反正最后解决办法如下: 1.把js文件复制到桌面: 2.打开文件并用另存为u ...

  4. 运行第一个SparkKPI程序

    1.复制一个examples中SparkPi.scala到IntelliJ IDEA编辑器,运行,出现错误: “org.apache.spark.SparkException: A master UR ...

  5. Lucene + Hadoop 分布式搜索运行框架 Nut 1.0a9转自http://www.linuxidc.com/Linux/2012-02/53113.htm

    1.概述 不管程序性能有多高,机器处理能力有多强,都会有其极限.能够快速方便的横向与纵向扩展是Nut设计最重要的原则,以此原则形成以分布式并行计算为核心的架构设计.以分布式并行计算为核心的架构设计是N ...

  6. js表单提交,判断文本框,用户名密码是否为空,JS表单检测!

    当表单提交时先触发验证的js代码,当验证表单的方法返回true时才会提交表单返回false则不提交数据<script type="text/javascript">fu ...

  7. Python -- OOP高级 -- 元类

    type()函数既可以返回一个对象的类型,又可以创建出新的类型 def fn(self, name="world"): print("Hello, %s!" % ...

  8. 用cas来实现php的单点登陆

    最近项目中需要做单点登录,客户端包含Java.ruby和PHP,java有几个应用程序,php是discuz+supesite+ucenter,配置步骤如下: 1.cas服务端:下载地址:http:/ ...

  9. Windows恢复Grub引导,用grub安装ubuntu

    http://www.linuxidc.com/wap.aspx?nid=18027&p=&cp=&cid=http://m.blog.chinaunix.net/uid-22 ...

  10. 支付宝集成+网站支付+APP支付+手机网站支付

    网站支付宝 1.申请签约后获得相应的pid:208***开头和key 这里说明下pc网站支付采用md5加密所以这里只需要提供pid和key不需要上传公钥. 2.下载即时到账demo http://do ...