题目描述

给定一张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. 网络1712--c语言函数作业总结

    作业亮点 1.总体情况 很多同学在思路方面大部分写的都很详细,能够通过思路回顾自己的代码 大部分同学都认真完成PTA,也充分利用了函数来解题 大部分同学能够从上机考试中总结自己的失误和不足点,制订了自 ...

  2. Alpha冲刺Day5

    Alpha冲刺Day5 一:站立式会议 今日安排: 首先由于经过黄腾飞短暂的测试,发现导入导出仍然有一些问题,今天需要进行完善 由黄腾飞负责企业自查风险管理子模块,要求为单元进行风险点的管理 由张梨贤 ...

  3. Linux进程间通信--信号量

    信号量绝对不同于信号,一定要分清,关于信号,上一篇博客中已经说过,如有疑问,请移驾! 信号量 一.是什么   信号量的本质是一种数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的通信资源(文件 ...

  4. python 特殊方法实例

    import collections from random import choice card = collections.namedtuple('Card',['rank','suit']) # ...

  5. cpp常用函数总结

    //sprintf sprintf(temp_str_result, "%lf", temp_double); result = temp_str_result; (*begin) ...

  6. 个人技术博客(alpha)

    APP的权限校验不同于web网页端,web一般使用session记录用户的状态信息,而app则使用token令牌来记录用户信息.有这样一个场景,系统的数据量达到千万级,需要几台服务器部署,当一个用户在 ...

  7. :after/:before使用技巧

    伪类:after/:before基本使用 div:before{ content:'';//必须要写,没写则伪元素无效 display:; position:''; ... } //在一个div子元素 ...

  8. 【Fungus入门】10分钟快速构建Unity中的万能对话系统 / 叙事系统 / 剧情系统

    我真的很久没有写过一个完整的攻略了(笑),咸鱼了很久之后还是想来写一个好玩的.这次主要是梳理一下Unity的小众插件Fungus的核心功能,并且快速掌握其使用方法. 官方文档:http://fungu ...

  9. 数据结构与算法 —— 链表linked list(01)

    链表(维基百科) 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer).由于不必须按顺序存储, ...

  10. ArrayList源码学习----JDK1.7

    什么是ArrayList? ArrayList是存储一组数据的集合,底层也是基于数组的方式实现,实际上也是对数组元素的增删改查:它的主要特点是: 有序:(基于数组实现) 随机访问速度快:(进行随机访问 ...