bzoj 4537 最小公倍数
给定一张N个顶点M条边的无向图 每条边上带有权值 所有权值都可以分解成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,那么称路径为简单路径
思路:
对于每个询问(u,v,A,B),将a<=A和b<=B的边全部加入并查集中,最后判断u和v是否在同一连通分量中且连通分量包含的最大的a=A,最大的b=B即可
把询问和边离线按a排序,询问时在已经加入的边中按b值排序加入并查集中
结合起来,按a值将询问和边分块,前面的边按第二种做法做,块内的边按第一种做法做就行了
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define inf 2139062143
#define ll long long
#define MAXN 100100
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-;ch=getchar();}
while(isdigit(ch)) {x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,m,T,fa[MAXN],rnk[MAXN],f,pos,b,mxp[MAXN],mxq[MAXN],top,cnt,size,ans[MAXN];
struct data
{
int u,v,p,q,pos;
bool operator < (const data & a) const {return q<a.q||(q==a.q&&pos<a.pos);}
}qs[MAXN],e[MAXN<<],tmp[MAXN<<];
struct stck{int u,v,rnk,p,q;}st[MAXN<<];
int find(int x) {return x==fa[x]?x:find(fa[x]);}
void merge(int u,int v,int p,int q)
{
int x=find(u),y=find(v);
if(rnk[x]<rnk[y]) swap(x,y);
st[++top]=(stck) {x,y,rnk[x],mxp[x],mxq[x]};
fa[y]=x;
mxp[x]=max(p,max(mxp[y],mxp[x]));
mxq[x]=max(q,max(mxq[x],mxq[y]));
if(rnk[x]==rnk[y]) rnk[x]++;
}
bool Cmp(data a,data b) {return a.p<b.p||(a.p==b.p&&a.q<b.q);}
void dlt()
{
fa[st[top].v]=st[top].v,rnk[st[top].u]=st[top].rnk,mxp[st[top].u]=st[top].p,mxq[st[top].u]=st[top].q,top--;
}
int main()
{
//freopen("al.in","r",stdin);
//freopen("al.out","w",stdout);
n=read(),m=read();int x,y,tot=;
for(int i=;i<=m;i++)
e[i].u=read(),e[i].v=read(),e[i].p=read(),e[i].q=read(),e[i].pos=;
size=sqrt(m*);
sort(e+,e+m+,Cmp);
T=read();
for(int i=;i<=T;i++)
qs[i].u=read(),qs[i].v=read(),qs[i].p=read(),qs[i].q=read(),qs[i].pos=i;
sort(qs+,qs+T+,Cmp);
for(int i=;i<=m;i++)
{
if((++tot==size)||i==m)
{
cnt=;
for(int j=;j<=i-tot;j++) tmp[++cnt]=e[j];
for(int j=;j<=T;j++)
if(qs[j].p>=e[i-cnt+].p&&(i==m||qs[j].p<e[i+].p)) tmp[++cnt]=qs[j];
if(i-tot!=cnt)
{
for(int j=;j<=n;j++) fa[j]=j,rnk[j]=,mxp[j]=mxq[j]=-;
sort(tmp+,tmp+cnt+);top=;
for(int j=;j<=cnt;j++)
{
if(tmp[j].pos)
{
for(int k=i-tot+;k<=i+;k++)
{
if(e[k].p>tmp[j].p||k>i)
{
int x=find(tmp[j].u),y=find(tmp[j].v);
if(x==y&&mxp[x]==tmp[j].p&&mxq[x]==tmp[j].q) ans[tmp[j].pos]=;
for(int l=i-tot+;l<=k-;l++) if(e[l].q<=tmp[j].q) dlt();
break;
}
if(e[k].q<=tmp[j].q) merge(e[k].u,e[k].v,e[k].p,e[k].q);
}
}
else merge(tmp[j].u,tmp[j].v,tmp[j].p,tmp[j].q);
}
}
tot=;
}
}
for(int i=;i<=T;i++)
puts(ans[i]?"Yes":"No");
}
bzoj 4537 最小公倍数的更多相关文章
- BZOJ 4537: [Hnoi2016]最小公倍数 [偏序关系 分块]
4537: [Hnoi2016]最小公倍数 题意:一张边权无向图,多组询问u和v之间有没有一条a最大为a',b最大为b'的路径(不一定是简单路径) 首先想到暴力做法,题目要求就是判断u和v连通,并查集 ...
- bzoj 4537 HNOI2016 最小公倍数
Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,-,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在有q个询问,每次询问给定四个参数u.v.a和b,请你 ...
- [BZOJ 4537][Hnoi 2016]最小公倍数
传送门 并查集+分块 看到题目可以想到暴力做法, 对于每个询问, 将所有a和b小于等于询问值的的边加入图中(用并查集), 如果询问的u和v在一个联通块中, 且该联通块的maxa和maxb均等与询问的a ...
- bzoj 4537: [Hnoi2016]最小公倍数 分块+并查集
题目大意: 给定一张n个点m条边的无向图,每条边有两种权.每次询问某两个点之间是否存在一条路径上的边的两种权的最大值分别等于给定值. n,q <= 50000. m <= 100000 题 ...
- 4537: [Hnoi2016]最小公倍数
Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,…,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在有q个询问,每次询问给定四个参数u.v.a和b,请你 ...
- 【BZOJ】【1025】【SCOI2009】游戏
DP/整数拆分 整个映射关系可以分解成几个循环(置换群的预备知识?),那么总行数就等于各个循环长度的最小公倍数+1(因为有个第一行的1~N).那么有多少种可能的排数就等于问有多少种可能的最小公倍数. ...
- 【BZOJ】【2154】Crash的数字表格
莫比乌斯反演 PoPoQQQ讲义第4题 题解:http://www.cnblogs.com/jianglangcaijin/archive/2013/11/27/3446169.html 感觉两次sq ...
- 【莫比乌斯反演】关于Mobius反演与lcm的一些关系与问题简化(BZOJ 2154 crash的数字表格&&BZOJ 2693 jzptab)
BZOJ 2154 crash的数字表格 Description 今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple).对于两个正整数a和b,LCM(a, b ...
- [BZOJ 1025] [SCOI2009] 游戏 【DP】
题目链接:BZOJ - 1025 题目分析 显然的是,题目所要求的是所有置换的每个循环节长度最小公倍数的可能的种类数. 一个置换,可以看成是一个有向图,每个点的出度和入度都是1,这样整个图就是由若干个 ...
随机推荐
- maven deploy时报错
Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on p ...
- 关于Linux字符集的查看及修改
一·查看字符集 字符集在系统中体现形式是一个环境变量,其查看当前终端使用字符集的方式可以有以下几种方式: 1.[root@ ~]# echo $LANG en_US.UTF-8 ...
- wannafly-day1 Problem A - Birthday
思路:队友贪心WA了,然后就没有然后了,自己也是第一次接触最小费用流的题.借这个题来学习一下,利用Spfa每次来找到一个最短的路径同时保存路径,每一次寻找最短路径就将这条路的最小费用流给剪掉,然后继续 ...
- PAT 1133 Splitting A Linked List
Given a singly linked list, you are supposed to rearrange its elements so that all the negative valu ...
- 使用NamedParameterJdbcTemplate
[在JDBC模板中使用具名参数] 1.在经典的JDBC用法中,SQL参数使用占位符?表示,并且受到位置的限制.定为参数的问题在于,一旦参数的顺序发生变化,就必须改变参数绑定. 2.在Spring JD ...
- 【Codeforces 1118D1】Coffee and Coursework (Easy version)
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 从小到大枚举天数. 然后贪心地,从大到小分配a[i]到各个天当中. a[n]分配到第1天,a[n-1]分配到第2天,...然后a[n-x]又分 ...
- 用Windows自带DOS命令提示符 制作U盘启动盘
Windows & DOS命令提示符 & U盘 & 启动盘 用Windows自带DOS命令提示符 制作U盘启动盘.docx http://xgqfrms.blog.163.co ...
- HDU 1542 Atlantics 线段树+离散化扫描
将 x 轴上的点进行离散化,扫描线沿着 y 轴向上扫描 每次添加一条边不断找到当前状态有效边的长度 , 根据这个长度和下一条边形成的高度差得到一块合法的矩形的面积 #include<iostre ...
- [BZOJ2594] [Wc2006]水管局长数据加强版(LCT + kruskal + 离线)
传送门 WC这个题真是丧心病狂啊,就是想学习一下怎么处理边权,给我来了这么一个破题! ORZ hzwer 临摹黄学长代码233 但还是复杂的一匹 理一下思路吧 题目大意:给定一个无向图,多次删除图中的 ...
- 分块试水--CODEVS4927 线段树练习5
模板 #include<stdio.h> #include<algorithm> #include<string.h> #include<stdlib.h&g ...