[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),每条边上带有权值.所有权值都可以分 ...
随机推荐
- 201621123060《JAVA程序设计》第十三周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 为了让你的系统可以被多个用户通过网 ...
- scrapy 修改URL爬取起始位置
import scrapy from Autopjt.items import myItem from scrapy.http import Request class AutospdSpider(s ...
- Beta冲刺Day3
项目进展 李明皇 今天解决的进度 完善了程序的运行逻辑(消息提示框等) 明天安排 前后端联动调试 林翔 今天解决的进度 向微信官方申请登录验证session以维护登录态 明天安排 继续完成维护登录态 ...
- 【作业】HansBug的前三次OO作业分析与小结
OO课程目前已经进行了三次的作业,容我在本文中做一点微小的工作. 第一次作业 第一次作业由于难度不大,所以笔者程序实际上写的也比较随意一些.(点击就送指导书~) 类图 程序的大致结构如下: 代码分析 ...
- 微信小程序轮播图
swiper标签 <!--index.wxml--> <swiper class="swiper" indicator-dots="true" ...
- MySQL-压缩版-windows安装
1.首先去dev.mysql.com/downloads/mysql/下载MySQL的压缩包,然后解压到任意盘符下. 2.打开系统变量在Path下追加mysql的路径(例如:C:\mysql-5.7. ...
- MySQL/MariaDB中游标的使用
本文目录:1.游标说明2.使用游标3.游标使用示例 1.游标说明 游标,有些地方也称为光标.它的作用是在一个结果集中逐条逐条地获取记录行并操作它们. 例如: 其中select是游标所操作的结果集,游标 ...
- AngularJS1.X学习笔记12-Ajax
说到Ajax,你一定是思绪万千,想到XMLHttpRequest,$.ajax(),跨域,异步之类的.本文将探讨一下AngularJS的Ajax. 一.一个简单的例子 <!DOCTYPE htm ...
- python random 模块的用法
Python中的random模块用于生成随机数.下面介绍一下random模块中最常用的几个函数. random.random random.random()用于生成一个0到1的随机符点数: 0 < ...
- python中的赋值与深浅拷贝
Python当中对于拷贝,分为两种类型.一种是数字和字符串,另一种就是列表.元组.字典等其他类型了. 一.数字和字符串的拷贝 1.赋值 举个栗子: a1 = 123123 a2 = 123123 # ...