[BZOJ4537][HNOI2016]最小公倍数(分块+并查集)
4537: [Hnoi2016]最小公倍数
Time Limit: 40 Sec Memory Limit: 512 MB
Submit: 1687 Solved: 607
[Submit][Status][Discuss]Description
给定一张N个顶点M条边的无向图(顶点编号为1,2,…,n),每条边上带有权值。所有权值都可以分解成2^a*3^b
的形式。现在有q个询问,每次询问给定四个参数u、v、a和b,请你求出是否存在一条顶点u到v之间的路径,使得
路径依次经过的边上的权值的最小公倍数为2^a*3^b。注意:路径可以不是简单路径。下面是一些可能有用的定义
:最小公倍数:K个数a1,a2,…,ak的最小公倍数是能被每个ai整除的最小正整数。路径:路径P:P1,P2,…,Pk是顶
点序列,满足对于任意1<=i<k,节点Pi和Pi+1之间都有边相连。简单路径:如果路径P:P1,P2,…,Pk中,对于任意1
<=s≠t<=k都有Ps≠Pt,那么称路径为简单路径。Input
输入文件的第一行包含两个整数N和M,分别代表图的顶点数和边数。接下来M行,每行包含四个整数u、v、a、
b代表一条顶点u和v之间、权值为2^a*3^b的边。接下来一行包含一个整数q,代表询问数。接下来q行,每行包含四
个整数u、v、a和b,代表一次询问。询问内容请参见问题描述。1<=n,q<=50000、1<=m<=100000、0<=a,b<=10^9Output
对于每次询问,如果存在满足条件的路径,则输出一行Yes,否则输出一行 No(注意:第一个字母大写,其余
字母小写) 。Sample Input
4 5
1 2 1 3
1 3 1 2
1 4 2 1
2 4 3 2
3 4 2 2
5
1 4 3 3
4 2 2 3
1 3 2 2
2 3 2 2
1 3 4 4Sample Output
Yes
Yes
Yes
No
NoHINT
Source
首先如果只有一个参数a,可以直接将边和询问排序然后扫一遍即可。
现在是二维偏序问题,我们就需要合理分块了。
将边按a排序,询问按b排序,考虑分块,每次找到所有第一关键字在[L,R]中的询问,那么我们将第一关键字在[1,L)的边按第二关键字排序,就可以指针扫一遍统计答案了,对于块内的问题,直接暴力合并和撤销并查集操作即可。
#include<cmath>
#include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
using namespace std; const int N=;
struct E{ int x,y,u,v,k; }a[N],b[N],c[N],h[N];
void up(int &x,int y){ if (x<y) x=y; } bool ans[N];
int n,m,cnt,tot,fa[N],sz[N],fu[N],fv[N];
bool cmpu(const E &p,const E &q){ return p.u<q.u || (p.u==q.u && p.v<q.v); }
bool cmpv(const E &p,const E &q){ return p.v<q.v || (p.v==q.v && p.u<q.u); }
int getfa(int x){ return (x==fa[x]) ? x : getfa(fa[x]); } void merge(int x,int y,int u,int v){
x=getfa(x); y=getfa(y); if (sz[x]>sz[y]) swap(x,y);
h[++tot]=(E){x,y,fu[y],fv[y],sz[y]};
if (x!=y) fa[x]=y,sz[y]+=sz[x],up(fu[y],fu[x]),up(fv[y],fv[x]);
up(fu[y],u); up(fv[y],v);
} int main(){
freopen("bzoj4537.in","r",stdin);
freopen("bzoj4537.out","w",stdout);
scanf("%d%d",&n,&m);
rep(i,,m) scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].u,&a[i].v);
sort(a+,a+m+,cmpu); scanf("%d",&cnt);
rep(i,,cnt) scanf("%d%d%d%d",&b[i].x,&b[i].y,&b[i].u,&b[i].v),b[i].k=i;
sort(b+,b+cnt+,cmpv);
int bl=sqrt(m);
for (int i=; i<=m; i+=bl){
rep(j,,n) fa[j]=j,fu[j]=fv[j]=-,sz[j]=;
int len=;
rep(j,,cnt) if (b[j].u>=a[i].u && (i+bl>m || b[j].u<a[i+bl].u)) c[++len]=b[j];
if (!len) continue;
if (i>) sort(a+,a+i,cmpv);
for (int j=,k=; j<=len; j++){
for (; k<i && a[k].v<=c[j].v; k++) merge(a[k].x,a[k].y,a[k].u,a[k].v);
tot=;
for (int l=i; l<i+bl && l<=m; l++)
if (a[l].u<=c[j].u && a[l].v<=c[j].v) merge(a[l].x,a[l].y,a[l].u,a[l].v);
int p=getfa(c[j].x),q=getfa(c[j].y);
ans[c[j].k]=(p==q && fu[p]==c[j].u && fv[p]==c[j].v);
for (; tot; tot--) p=h[tot].x,q=h[tot].y,fa[p]=p,fu[q]=h[tot].u,fv[q]=h[tot].v,sz[q]=h[tot].k;
}
}
rep(i,,cnt) puts(ans[i]?"Yes":"No");
return ;
}
[BZOJ4537][HNOI2016]最小公倍数(分块+并查集)的更多相关文章
- bzoj 4537: [Hnoi2016]最小公倍数 分块+并查集
题目大意: 给定一张n个点m条边的无向图,每条边有两种权.每次询问某两个点之间是否存在一条路径上的边的两种权的最大值分别等于给定值. n,q <= 50000. m <= 100000 题 ...
- 洛谷P3247 最小公倍数 [HNOI2016] 分块+并查集
正解:分块+并查集 解题报告: 传送门! 真的好神仙昂QAQ,,,完全想不出来,,,还是太菜了QAQ 首先还是要说下,这题可以用K-D Tree乱搞过去(数据结构是个好东西昂,,,要多学学QAQ),但 ...
- [APIO2019] [LOJ 3145] 桥梁(分块+并查集)(有详细注释)
[APIO2019] [LOJ 3145] 桥梁(分块+并查集)(有详细注释) 题面 略 分析 考试的时候就感觉子任务4是突破口,结果却写了个Kruskal重构树,然后一直想怎么在线用数据结构维护 实 ...
- P5443 [APIO2019]桥梁 [分块+并查集]
分块+并查集,大板子,没了. 并查集不路径压缩,可撤销,然后暴力删除 这样对于每个块都是独立的,所以直接搞就行了. 然后块内修改操作搞掉,就是单独的了 // powered by c++11 // b ...
- [BZOJ4537][Hnoi2016]最小公倍数 奇怪的分块+可撤销并查集
4537: [Hnoi2016]最小公倍数 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1474 Solved: 521[Submit][Stat ...
- BZOJ4537 HNOI2016最小公倍数(莫队+并查集)
考虑边只有一种权值的简化情况.那么当且仅当两点可以通过边权<=x的边连通,且连通块内最大边权为x时,两点间存在路径max为x的路径.可以发现两种权值是类似的,当且仅当两点可以通过边权1<= ...
- 洛谷P3247 [HNOI2016]最小公倍数(分块 带撤销加权并查集)
题意 题目链接 给出一张带权无向图,每次询问\((u, v)\)之间是否存在一条路径满足\(max(a) = A, max(b) = B\) Sol 这题居然是分块..想不到想不到..做这题的心路历程 ...
- 洛谷P3247 [HNOI2016]最小公倍数 [分块,并查集]
洛谷 思路 显然,为了达到这个最小公倍数,只能走\(a,b\)不是很大的边. 即,当前询问的是\(A,B\),那么我们只能走\(a\leq A,b\leq B\)的边. 然而,为了达到这最小公倍数,又 ...
- 【BZOJ4537】[Hnoi2016]最小公倍数 分块
[BZOJ4537][Hnoi2016]最小公倍数 Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,…,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在 ...
随机推荐
- python中的Queue模块
queue介绍 queue是python的标准库,俗称队列.可以直接import引用,在python2.x中,模块名为Queue.python3直接queue即可 在python中,多个线程之间的数据 ...
- 【Python学习笔记】使用Python进行主成分分析
使用sklearn库中的PCA类进行主成分分析. 导入要用到的库,还没有的直接pip安装就好了. from sklearn.decomposition import PCA import numpy ...
- [Leetcode Week14]Path Sum II
Path Sum II 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/path-sum-ii/description/ Description Giv ...
- Linux进程调度与源码分析(二)——进程生命周期与task_struct进程结构体
1.进程生命周期 Linux操作系统属于多任务操作系统,系统中的每个进程能够分时复用CPU时间片,通过有效的进程调度策略实现多任务并行执行.而进程在被CPU调度运行,等待CPU资源分配以及等待外部事件 ...
- Linux时间子系统之八:动态时钟框架(CONFIG_NO_HZ、tickless)【转】
转自:http://blog.csdn.net/droidphone/article/details/8112948 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 数据结 ...
- ue4.3正式版源码链接
ue4.3正式版源码链接 http://tieba.baidu.com/p/3170253742
- http状态码+http请求方式
一.http状态码 2开头 (请求成功)表示成功处理了请求的状态代码. 200 (成功) 服务器已成功处理了请求. 通常,这表示服务器提供了请求的网页. 201 (已创建) 请求成功并且服 ...
- Python爬虫音频数据
一:前言 本次爬取的是喜马拉雅的热门栏目下全部电台的每个频道的信息和频道中的每个音频数据的各种信息,然后把爬取的数据保存到mongodb以备后续使用.这次数据量在70万左右.音频数据包括音频下载地址, ...
- An In-Depth Look at the HBase Architecture
https://www.mapr.com/blog/in-depth-look-hbase-architecture An In-Depth Look at the HBase Architectur ...
- python 数据类型 变量 注释
基本数据类型: 数字 number :整数 int . 浮点数 float.复数 complex.布尔值 bool 列表 list : 使用 方括号 [] 表示,例如: [1,2,'abc'] ...