http://www.lydsy.com/JudgeOnline/problem.php?id=4537 (题目链接)

题意

  给出一个${n}$个点${m}$条边的无向图,每条边有两个权值${a,b}$。给出$Q$个询问,问$u,v$两点间是否存在一条路径(可以不是简单路径),使得路径上的边的最大$a,b$正好等于$A,B$。

Solution

  http://blog.csdn.net/zmh964685331/article/details/51194393

  我们考虑按照$a$的权值分块。每次找到$a$的权值在块内的询问,对它们进行处理。

  将这些询问按照$b$的大小排序以后,我们用并查集维护图的连通性。此时的边有两类,第一类就是在之前的块中的边,这些边的$a$肯定是小于询问的$a$的,我们将这些边按照$b$排序,然后依次加入。第二类就是在当前块中的边,这些边我们不好处理,直接暴for过去,如果它们的$a,b$都小于询问的$a,b$,就加入到图中,做完之后再将这些边暴力还原,因为只有$\sqrt{m}$条,所以不虚。

  并查集按秩合并,同时维护连通块中$a,b$的最值。查询的时候就是判断是否$u,v$在同一连通块中,这个连通块$a,b$的最大值是否正好等于询问的$a,b$。

细节

  块的大小,开大一点,不然会TLE。

  如果大块大块相同的$a$,我们的询问会被重复不断的加入,这是很浪费的,所以我们对这种情况进行一些处理。

  bzoj是有多慢,本机20s,交上去几乎要TLE。。。

代码

// bzoj4537
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf (1ll<<30)
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;
inline int gi() {
int x=0,f=1;char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
return x*f;
} const int maxn=100010;
int ans[maxn],Q,n,m,top,tot,S;
int fa[maxn],da[maxn],db[maxn],size[maxn];
struct option {int u,v,da,db,fa,size;}op[maxn];
struct data {int u,v,a,b,id;}e[maxn],q[maxn],tmp[maxn]; inline bool cmpa(data a,data b) {return a.a==b.a ? a.b<b.b : a.a<b.a;}
inline bool cmpb(data a,data b) {return a.b==b.b ? a.a<b.a : a.b<b.b;} inline int find(int x) {
return fa[x]==x ? x : find(fa[x]);
}
inline void Union(int u,int v,int a,int b) {
u=find(u),v=find(v);
if (size[u]>size[v]) swap(u,v);
op[++tot]=(option){u,v,da[v],db[v],fa[u],size[v]};
if (u==v) da[v]=max(da[v],a),db[v]=max(db[v],b);
else {
fa[u]=v;size[v]+=size[u];
da[v]=max(da[v],max(da[u],a));
db[v]=max(db[v],max(db[u],b));
}
}
int main() {
n=gi(),m=gi();
for (int i=1;i<=m;i++) e[i].u=gi(),e[i].v=gi(),e[i].a=gi(),e[i].b=gi(),e[i].id=i;
S=(int)sqrt(3*m);
Q=gi();
for (int i=1;i<=Q;i++) q[i].u=gi(),q[i].v=gi(),q[i].a=gi(),q[i].b=gi(),q[i].id=i;
sort(e+1,e+1+m,cmpa);
sort(q+1,q+1+Q,cmpb);
for (int i=1;i<=m;i+=S) {
int L=i,R=min(i+S-1,m);
top=0;
for (int j=1;j<=Q;j++)
if (q[j].a>=e[L].a && (R==m || q[j].a<e[R+1].a)) tmp[++top]=q[j]; //考虑很多边a相等的情况
sort(e+1,e+L,cmpb);
for (int j=1;j<=n;j++) fa[j]=j,size[j]=1,da[j]=db[j]=-1;
for (int j=1,k=1;j<=top;j++) {
for (;k<L && e[k].b<=tmp[j].b;k++) Union(e[k].u,e[k].v,e[k].a,e[k].b);
tot=0;
for (int l=L;l<=R;l++)
if (e[l].a<=tmp[j].a && e[l].b<=tmp[j].b) Union(e[l].u,e[l].v,e[l].a,e[l].b);
int u=find(tmp[j].u),v=find(tmp[j].v);
ans[tmp[j].id]= u==v && da[u]==tmp[j].a && db[u]==tmp[j].b;
for (;tot;tot--) {
fa[op[tot].u]=op[tot].fa;
db[op[tot].v]=op[tot].db;
da[op[tot].v]=op[tot].da;
size[op[tot].v]=op[tot].size;
}
}
}
for (int i=1;i<=Q;i++) printf(ans[i] ? "Yes\n" : "No\n");
return 0;
}

【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 最小公倍数

    首先将边按a的值分组,每$\sqrt{m}$一组. 对于每一组,将符合一组a的询问选出来,将这些询问和这一块之前的边(a一定小于这些询问)按b排序,然后交替插入,询问,对于一个询问,在当前块也有可能有 ...

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

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

随机推荐

  1. 解决php的交互式命令行不能正常启动的问题兼介绍psysh

    今天在自己的mac电脑上试着启动php的交互式命令行,发现敲下命令后一直卡在提示进入的地方,但没有出现已经进入的提示符,百度了下应该是与readline有关. 于是安装php的readline扩展,在 ...

  2. 关于this指向,翻到的

    关于JavaScript函数执行环境的过程,IBM developerworks文档库中的一段描述感觉很不错,摘抄如下: “JavaScript 中的函数既可以被当作普通函数执行,也可以作为对象的方法 ...

  3. 20155331 Exp3 免杀原理与实践

    20155331 Exp3 免杀原理与实践 基础问题回答 杀软是如何检测出恶意代码的? 1.基于特征码的检测,2.启发式恶意软件检测,3.基于行为的恶意软件检测. 免杀是做什么? 让病毒不被杀毒软件杀 ...

  4. WPF后台线程更新UI

    0.讲点废话 最近在做一个文件搜索的小软件,当文件多时,界面会出现假死的状况,于是乎想到另外开一个后台线程,更新界面上的ListView,但是却出现我下面的问题. 1.后台线程问题 2年前写过一个软件 ...

  5. WinDbg命令三部曲

    WinDbg 命令三部曲:(一)WinDbg 命令手册 WinDbg 命令三部曲:(二)WinDbg SOS 扩展命令手册 WinDbg 命令三部曲:(三)WinDbg SOSEX 扩展命令手册

  6. Java虚拟机笔记(五):JVM中对象的分代

    为什么要分代 为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用, ...

  7. AppStore下载Xcode的文件

    有的时候团队开发,手机系统一升级,那么对应的Xcode也就需要升级了,由于团队开发,可能一下要把所有人的都升级一下,那么最简单的就是下好一份Xcode然后分享给大家. 但是有的时候你就会发现,通过Ap ...

  8. Python对Selenium调用浏览器进行封装包括启用无头浏览器,及对应的浏览器配置文件

    """ 获取浏览器 打开本地浏览器 打开远程浏览器 关闭浏览器 打开网址 最大化 最小化 标题 url 刷新 Python对Selenium封装浏览器调用 ------b ...

  9. linux 操作 mysql 指定端口登录 以及启动 停止

    linux 操作 mysql 指定端口登录 mysql -uroot -p -h10.154.0.43 -P3341 1.查看mysql版本方法一:status;方法二:select version( ...

  10. Mabatis中#{}和${}的区别

    动态 sql 是 mybatis 的主要特性之一,在 mapper 中定义的参数传到 xml 中之后,在查询之前 mybatis 会对其进行动态解析.mybatis 为我们提供了两种支持动态 sql ...