[HNOI2016]最小公倍数
题目描述
给定一张N个顶点M条边的无向图(顶点编号为1,2,...,n),每条边上带有权值。所有权值都可以分解成2a∗3b2^a*3^b2a∗3b 的形式。
现在有q个询问,每次询问给定四个参数u、v、a和b,请你求出是否存在一条顶点u到v之间的路径,使得路径依次经过的边上的权值的最小公倍数为2a∗3b2^a*3^b2a∗3b 。
注意:路径可以不是简单路径。下面是一些可能有用的定义:最小公倍数:K个数a1,a2,...,ak的最小公倍数是能被每个ai整除的最小正整数。
路径:路径P:P1,P2,...,Pk是顶点序列,满足对于任意1<=i<k,节点Pi和Pi+1之间都有边相连。简单路径:如果路径P:P1,P2,...,Pk中,对于任意1≤s≠t≤k1\le s\ne t\le k1≤s≠t≤k 都有Ps≠PtPs\ne PtPs≠Pt ,那么称路径为简单路径。
输入输出格式
输入格式:
输入文件的第一行包含两个整数N和M,分别代表图的顶点数和边数。接下来M行,每行包含四个整数u、v、a、b代表一条顶点u和v之间、权值为2a∗3b2^a*3^b2a∗3b 的边。接下来一行包含一个整数q,代表询问数。接下来q行,每行包含四个整数u、v、a和b,代表一次询问。询问内容请参见问题描述。1<=n,q<=50000、1<=m<=100000、0<=a,b<=10^9
输出格式:
对于每次询问,如果存在满足条件的路径,则输出一行Yes,否则输出一行 No(注意:第一个字母大写,其余字母小写) 。
输入输出样例
Yes
Yes
Yes
No
No
对于每个询问,我们可以把所有(a,b)小于等于的边加入并查集
并查集维护联通块的最大a和最大b,分别为Maxa,Maxb
如果最大(Maxa,Maxb)=(a,b)
暴力显然不行
现将边按a排序,分块
将询问按b排序
每一块加入a值在这一块的范围内的询问,即大于等于a[i]小于a[i+√m]
前面的块里的边显然a值都符合需求,按b排序
从前往后枚举加入的询问,将前面块里小于b的边加入
因为满足当前询问的边,必定也满足下一个询问,所以不需要撤销
然后枚举当前块里的边加入,处理完当前询问要撤销并查集的操作
因为撤销操作需要储存状态并复原,只有根号个撤销操作,复杂度有保证
不能用路径压缩
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct Node
{
int u,v,a,b,id;
}e[],q[],pre[],p[];
int set[],tot,Maxa[],Maxb[],n,m,lim,r,cnt,ans[],size[];
int gi()
{
char ch=getchar();
int x=;
while (ch<''||ch>'') ch=getchar();
while (ch>=''&&ch<='')
{
x=(x<<)+(x<<)+ch-'';
ch=getchar();
}
return x;
}
bool cmpa(Node x,Node y)
{
if (x.a==y.a) return x.b<y.b;
return x.a<y.a;
}
bool cmpb(Node x,Node y)
{
if (x.b==y.b) return x.a<y.a;
return x.b<y.b;
}
int find(int x)
{
if (set[x]==x) return x;
if (set[x]!=x) return find(set[x]);
}
void merge(Node E)
{
int p=find(E.u),q=find(E.v);
if (size[p]<size[q]) swap(p,q);
++tot;
pre[tot].u=p,pre[tot].v=q,pre[tot].a=Maxa[p],pre[tot].b=Maxb[p];pre[tot].id=size[p];
if (p!=q)
{
set[q]=p;
size[p]+=size[q];
}
if (Maxa[p]<E.a)
Maxa[p]=E.a;
if (Maxa[p]<Maxa[q])
Maxa[p]=Maxa[q];
if (Maxb[p]<E.b)
Maxb[p]=E.b;
if (Maxb[p]<Maxb[q])
Maxb[p]=Maxb[q];
}
void undo()
{int i;
Node E;
for (;tot;tot--)
{
E=pre[tot];
set[E.v]=E.v;
Maxa[E.u]=E.a;
Maxb[E.u]=E.b;
size[E.u]=E.id;
}
}
int main()
{int i,j,k,l,ed,p1,p2;
cin>>n>>m;
lim=sqrt(m);
for (i=;i<=m;i++)
{
e[i].u=gi();e[i].v=gi();e[i].a=gi();e[i].b=gi();
e[i].id=i;
}
cin>>r;
for (i=;i<=r;i++)
{
q[i].u=gi();q[i].v=gi();q[i].a=gi();q[i].b=gi();
q[i].id=i;
}
sort(e+,e+m+,cmpa);
sort(q+,q+r+,cmpb);
for (i=;i<=m;i+=lim)
{
cnt=;tot=;
k=;
for (j=;j<=r;j++)
if (q[j].a>=e[i].a&&(i+lim>m||q[j].a<e[i+lim].a))
p[++cnt]=q[j];
if (cnt==0) continue;
sort(e+,e+i,cmpb);
if (i+lim-<=m) ed=i+lim-;
else ed=m;
for (j=;j<=n;j++)
set[j]=j,Maxa[j]=-,Maxb[j]=-,size[j]=;
for (j=;j<=cnt;j++)
{
for (;k<i;k++)
if (p[j].b>=e[k].b) merge(e[k]);
else break;
tot=;
for (l=i;l<=ed;l++)
if (p[j].b>=e[l].b&&p[j].a>=e[l].a)
{
merge(e[l]);
}
else if (e[l].a>p[j].a) break;
p1=find(p[j].u),p2=find(p[j].v);
if (p1==p2&&Maxa[p1]==p[j].a&&Maxb[p1]==p[j].b)
ans[p[j].id]=;
undo();
}
}
for (i=;i<=r;i++)
if (ans[i])
puts("Yes");
else puts("No");
}
[HNOI2016]最小公倍数的更多相关文章
- BZOJ 4537: [Hnoi2016]最小公倍数 [偏序关系 分块]
4537: [Hnoi2016]最小公倍数 题意:一张边权无向图,多组询问u和v之间有没有一条a最大为a',b最大为b'的路径(不一定是简单路径) 首先想到暴力做法,题目要求就是判断u和v连通,并查集 ...
- 【LG3247】[HNOI2016]最小公倍数
[LG3247][HNOI2016]最小公倍数 题面 洛谷 题解 50pts 因为拼凑起来的部分分比较多,所以就放一起了. 以下设询问的\(a,b\)为\(A,B\), 复杂度\(O(nm)\)的:将 ...
- [BZOJ4537][HNOI2016]最小公倍数(分块+并查集)
4537: [Hnoi2016]最小公倍数 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1687 Solved: 607[Submit][Stat ...
- [BZOJ4537][Hnoi2016]最小公倍数 奇怪的分块+可撤销并查集
4537: [Hnoi2016]最小公倍数 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1474 Solved: 521[Submit][Stat ...
- 【BZOJ4537】[Hnoi2016]最小公倍数 分块
[BZOJ4537][Hnoi2016]最小公倍数 Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,…,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在 ...
- 4537: [Hnoi2016]最小公倍数
Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,…,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在有q个询问,每次询问给定四个参数u.v.a和b,请你 ...
- bzoj 4537 HNOI2016 最小公倍数
Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,-,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在有q个询问,每次询问给定四个参数u.v.a和b,请你 ...
- 洛谷P3247 [HNOI2016]最小公倍数 [分块,并查集]
洛谷 思路 显然,为了达到这个最小公倍数,只能走\(a,b\)不是很大的边. 即,当前询问的是\(A,B\),那么我们只能走\(a\leq A,b\leq B\)的边. 然而,为了达到这最小公倍数,又 ...
- [HNOI2016]最小公倍数 (可回退并查集,回滚莫队)
题面 题目链接 题目描述 给定一张 N N N 个顶点 M M M 条边的无向图(顶点编号为 1 , 2 , - , n 1,2,\ldots,n 1,2,-,n),每条边上带有权值.所有权值都可以分 ...
随机推荐
- C语言博客作业--函数
一.PTA实验作业 题目1 (6-7) (1).本题PTA提交列表 (2)设计思路 设计第一个函数判断是否完数int factorsum( int number ) 定义sum.i:sum初始化归0, ...
- Archlinux无线联网教程
本人是学生党,故对于有线方式不甚了解,学校里一般使用mentohust用动态IP方式联网,或者直接连接wifi,这里介绍无线联网的一些方式,主要包括公共wifi和带有WEP或者WPA或者WPA2PSK ...
- win7开启wifi
在启用本地共享连接时,出现的错误! 我已经建了一个无线临时网络,来启用共享用来上网的!Internet连接共享访问被启用时,出现了一个错误(null)?而且这错误也会在系统日志里留下记录,都是些莫名其 ...
- JAVAGUI设计步骤
①创建容器 首先要创建一个GUI应用程序,需要创建一个用于容纳所有其它GUI组件元素的载体,Java中称为容器.典型的包括窗口(Window).框架(Frame/JFrame).对话框(Dialog/ ...
- JAVA接口基础知识总结
1:是用关键字interface定义的. 2:接口中包含的成员,最常见的有全局常量.抽象方法. 注意:接口中的成员都有固定的修饰符. 成员变量:public static final 成员方法 ...
- Java HashMap工作原理及实现
Java HashMap工作原理及实现 2016/03/20 | 分类: 基础技术 | 0 条评论 | 标签: HASHMAP 分享到:3 原文出处: Yikun 1. 概述 从本文你可以学习到: 什 ...
- DML数据操作语言之复杂查询
1.视图(View) 我们知道,在关系型数据库中,用来保存实际数据记录的是数据表.和表同等概念也是用来保存东西是:视图. 但是数据表是用来保存实际数据记录的,而视图是用来保存常用select语句的. ...
- ELK学习总结(4-1)elasticsearch更改mapping(不停服务重建索引)
elasticsearch更改mapping(不停服务重建索引)原文 http://donlianli.iteye.com/blog/1924721Elasticsearch的mapping一旦创建, ...
- redux的使用过程
1.redux是react的状态管理工具,可以用来存放公共数据,因此也可用来作为组件间参数传递的方法. 2.组件传参,需要有一个公共的父组件.在父组件中引入Provider.通过Provider将 ...
- 转:NLP+句法结构(三)︱中文句法结构(CIPS2016、依存句法、文法)
NLP+句法结构(三)︱中文句法结构(CIPS2016.依存句法.文法)转自:https://www.cnblogs.com/maohai/p/6453389.html 摘录自:CIPS2016 中文 ...