题目描述

给定一张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(注意:第一个字母大写,其余字母小写) 。

输入输出样例

输入样例#1:
复制

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 4
输出样例#1: 复制

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]最小公倍数的更多相关文章

  1. BZOJ 4537: [Hnoi2016]最小公倍数 [偏序关系 分块]

    4537: [Hnoi2016]最小公倍数 题意:一张边权无向图,多组询问u和v之间有没有一条a最大为a',b最大为b'的路径(不一定是简单路径) 首先想到暴力做法,题目要求就是判断u和v连通,并查集 ...

  2. 【LG3247】[HNOI2016]最小公倍数

    [LG3247][HNOI2016]最小公倍数 题面 洛谷 题解 50pts 因为拼凑起来的部分分比较多,所以就放一起了. 以下设询问的\(a,b\)为\(A,B\), 复杂度\(O(nm)\)的:将 ...

  3. [BZOJ4537][HNOI2016]最小公倍数(分块+并查集)

    4537: [Hnoi2016]最小公倍数 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 1687  Solved: 607[Submit][Stat ...

  4. [BZOJ4537][Hnoi2016]最小公倍数 奇怪的分块+可撤销并查集

    4537: [Hnoi2016]最小公倍数 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 1474  Solved: 521[Submit][Stat ...

  5. 【BZOJ4537】[Hnoi2016]最小公倍数 分块

    [BZOJ4537][Hnoi2016]最小公倍数 Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,…,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在 ...

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

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

  7. bzoj 4537 HNOI2016 最小公倍数

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

  8. 洛谷P3247 [HNOI2016]最小公倍数 [分块,并查集]

    洛谷 思路 显然,为了达到这个最小公倍数,只能走\(a,b\)不是很大的边. 即,当前询问的是\(A,B\),那么我们只能走\(a\leq A,b\leq B\)的边. 然而,为了达到这最小公倍数,又 ...

  9. [HNOI2016]最小公倍数 (可回退并查集,回滚莫队)

    题面 题目链接 题目描述 给定一张 N N N 个顶点 M M M 条边的无向图(顶点编号为 1 , 2 , - , n 1,2,\ldots,n 1,2,-,n),每条边上带有权值.所有权值都可以分 ...

随机推荐

  1. 铜齿铁牙UP计划

    铜齿铁牙UP计划 我在""做教练"之好声音训练"给出了老师.播音主持学习者,声乐学习者科学用声三要点: 用气发声 共鸣发声 虚实结合 用气发声首先要学会腹式呼吸 ...

  2. 《团队-OldNote-项目总结》

    我们小组做的是手机便签的app---OldNote 最开始我们想解决普通手机便签无法进行语音和照片的备忘这一问题,但是由于没有做过拍照和录音的经验怕由于技术原因无法达成目的,就没敢写在需求分析中.当完 ...

  3. listview、gradview滚动到最后时,滑动至顶部

    listview.gradview滑动顶端.底部的判断及底部滑动至顶端 mPhotoWall.setOnScrollListener(new AbsListView.OnScrollListener( ...

  4. 第四十四条:为所有导出的API元素编写文档注释

    简而言之,要为API编写文档,文档注释是最好,最有效的途径.对于所有可导出的API元素来说,使用文档注释应该被看作是强制性的.要 采用一致的风格来遵循标准的约定.记住,在文档注释内部出现任何的HTML ...

  5. Hibernate之深入Hibernate的映射文件

    这周周末 要把hibernate的映射文件搞定 .. 1.映射文件的主结构 主要结构  :根元素为<hibernate-mapping ></hibernate-mapping> ...

  6. c 语言的基本语法

    1,c的令牌(Tokens) printf("Hello, World! \n"); 这五个令牌是: printf ( "Hello, World! \n" ) ...

  7. es6学习笔记--Interator和Generator(以及for-of的用法)

    这几天学习了遍历器和生成器,看着资料学,有点雾里缭绕的感觉,让人忍不住放弃,还好多看了好几遍,怼着资料里的例子让自己学会了Interator和Generator.   Interator,中文简称:遍 ...

  8. http缓存浅谈

    我们在访问百度首页的时候,会发现不管怎么刷新页面,静态资源基本都是返回 200(from cache): 随便点开一个静态资源是酱的: 哎哟有Response报头数据呢,看来服务器也正常返回了etag ...

  9. 实现GridControl行动态改变行字体和背景色

    需求:开发时遇到一个问题, 需要根据GridControl行数据不同,实现不同的效果 在gridView的RowCellStyle的事件中实现,需要的效果 private void gridView1 ...

  10. sql server 常用的查询语句

    最近在加强sql 语句的学习,整理一下基本语法,现在记录下 select * from dbo.cangku where city='河南' select  distinct(city), cangk ...