洛谷


思路

显然,为了达到这个最小公倍数,只能走\(a,b\)不是很大的边。

即,当前询问的是\(A,B\),那么我们只能走\(a\leq A,b\leq B\)的边。

然而,为了达到这最小公倍数,又需要有\(\max\{a\}=A,\max\{b\}=B\)。

那么暴力做法就很显然了:并查集维护连通块的\(\max\{a\},\max\{b\}\),询问时把满足条件的边全都连上,看最终是否满足条件。

如何优化呢?

把边按\(a\)排序,撒\(\sqrt m\)个关键点,每个关键点把它前面的边按\(b\)排序。

每个询问找出\(a\leq A\)的最靠右关键点,把这个询问放进去。

每个关键点把询问按\(B\)排序。

在关键点回答询问时维护一个从左到右的指针。由于询问的\(B\)递增,指针可以一直从左往右扫。

然后把这个关键点到下一个关键点之间满足条件的边加进去,得到答案,再撤回。

假设\(n,m,q\)同阶(虽然实际上不同阶),则复杂度\(O(n\sqrt n\log n)​\),可能可以调整块大小得到更优的复杂度。


代码

注意\(a,b\)有0,一开始最大值要赋为-1。

由于使用了较多STL,需要开O2

#include<bits/stdc++.h>
clock_t t=clock();
namespace my_std{
using namespace std;
#define pii pair<int,int>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define sz 101010
#define S 350
typedef long long ll;
typedef double db;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template<typename T>inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
inline bool chkmax(int &x,int y){return x<y?x=y,1:0;}
template<typename T>inline void read(T& t)
{
t=0;char f=0,ch=getchar();double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
t=(f?-t:t);
}
template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
void file()
{
#ifndef ONLINE_JUDGE
freopen("a.txt","r",stdin);
#endif
}
inline void chktime()
{
#ifndef ONLINE_JUDGE
cout<<(clock()-t)/1000.0<<'\n';
#endif
}
#ifdef mod
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
ll inv(ll x){return ksm(x,mod-2);}
#else
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
#endif
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std; int n,m,Q;
struct hh{int u,v,a,b;}edge[sz];
inline bool cmp1(const hh &x,const hh &y){return x.a<y.a;}
inline bool cmp2(const hh &x,const hh &y){return x.b<y.b;}
bool ans[sz]; struct Query{int u,v,a,b,id;};
inline bool cmp(const Query &x,const Query &y){return x.b<y.b;}
int blo,num,val[S],pos[S];
vector<hh>v[S];
vector<Query>q[S];
void init()
{
chktime();
sort(edge+1,edge+m+1,cmp1);
blo=sqrt(m);num=m/blo+(bool)(m%blo);
rep(i,1,num) val[i]=edge[pos[i]=i*blo-blo].a;
chktime();
rep(i,1,num)
{
rep(j,1,pos[i]) v[i].push_back(edge[j]);
sort(v[i].begin(),v[i].end(),cmp2);
}
pos[num+1]=m+1;
}
int fa[sz],mx1[sz],mx2[sz],dep[sz];
int getfa(int x){return x==fa[x]?x:getfa(fa[x]);}
struct hhh{int x,y,mx1,mx2,d;};
hhh merge(hh e)
{
int x=getfa(e.u),y=getfa(e.v);
if (dep[x]>dep[y]) swap(x,y);
hhh ret=(hhh){x,y,mx1[y],mx2[y],dep[y]};
fa[x]=y;
chkmax(mx1[y],max(mx1[x],e.a));chkmax(mx2[y],max(mx2[x],e.b));
if (dep[x]==dep[y]) ++dep[y];
return ret;
}
inline void del(hhh s){fa[s.x]=s.x;mx1[s.y]=s.mx1;mx2[s.y]=s.mx2;dep[s.y]=s.d;}
void solve(int s)
{
sort(q[s].begin(),q[s].end(),cmp);
rep(i,1,n) fa[i]=i,mx1[i]=mx2[i]=-1,dep[i]=1;
int p=0;
rep(i,0,(int)q[s].size()-1)
{
int aa=q[s][i].a,bb=q[s][i].b;
while (p<=(int)v[s].size()-1&&v[s][p].b<=bb) merge(v[s][p]),++p;
stack<hhh>SS;
rep(j,pos[s]+1,pos[s+1]-1)
if (edge[j].a<=aa&&edge[j].b<=bb)
SS.push(merge(edge[j]));
int uu=getfa(q[s][i].u),vv=getfa(q[s][i].v);
if (uu==vv&&mx1[uu]==aa&&mx2[uu]==bb) ans[q[s][i].id]=1;
while (!SS.empty()) del(SS.top()),SS.pop();
}
} int main()
{
file();
int x,y,a,b;
read(n,m);
rep(i,1,m) read(x,y,a,b),edge[i]=(hh){x,y,a,b};
chktime();
read(Q);
init();
chktime();
rep(i,1,Q)
{
read(x,y,a,b);
int t=upper_bound(val+1,val+num+1,a)-val-1;
q[t].push_back((Query){x,y,a,b,i});
}
chktime();
rep(i,1,num) solve(i);
rep(i,1,Q) puts(ans[i]?"Yes":"No");
chktime();
return 0;
}

洛谷P3247 [HNOI2016]最小公倍数 [分块,并查集]的更多相关文章

  1. 洛谷P3247 [HNOI2016]最小公倍数(分块 带撤销加权并查集)

    题意 题目链接 给出一张带权无向图,每次询问\((u, v)\)之间是否存在一条路径满足\(max(a) = A, max(b) = B\) Sol 这题居然是分块..想不到想不到..做这题的心路历程 ...

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

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

  3. bzoj 4537: [Hnoi2016]最小公倍数 分块+并查集

    题目大意: 给定一张n个点m条边的无向图,每条边有两种权.每次询问某两个点之间是否存在一条路径上的边的两种权的最大值分别等于给定值. n,q <= 50000. m <= 100000 题 ...

  4. Bzoj1015/洛谷P1197 [JSOI2008]星球大战(并查集)

    题面 Bzoj 洛谷 题解 考虑离线做法,逆序处理,一个一个星球的加入.用并查集维护一下连通性就好了. 具体来说,先将被消灭的星球储存下来,先将没有被消灭的星球用并查集并在一起,这样做可以路径压缩,然 ...

  5. 洛谷1525 关押罪犯NOIP2010 并查集

    问题描述 S城现有两座监狱,一共关押着N名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值)来表示某两 ...

  6. 洛谷P1525 关押罪犯(并查集、二分图判定)

    本人蒟蒻,只能靠题解AC,看到大佬们的解题思路,%%%%%% https://www.luogu.org/problemnew/show/P1525 题目描述 S城现有两座监狱,一共关押着N名罪犯,编 ...

  7. 洛谷 P2661 信息传递 Label:并查集||强联通分量

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  8. 洛谷 P1111 修复公路 Label:并查集

    题目背景 A地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车.政府派人修复这些公路. 题目描述 给出A地区的村庄数N,和公路数M,公路是双向的.并告诉你每条公路的连着哪两个村庄,并告诉你什么时 ...

  9. 洛谷P3367 【模板】并查集

    P3367 [模板]并查集 293通过 551提交 题目提供者HansBug 标签 难度普及- 提交  讨论  题解 最新讨论 不知道哪错了 为啥通不过最后三个节点 题解 不懂为什么MLE 最后一个数 ...

随机推荐

  1. IIS7.5配置过程

    1.Windows功能,注意选择应用程序开发功能,否则不能使用经典模式. 2.Cmd运行(使用.netframework4.0)C:\Windows\Microsoft.NET\Framework\V ...

  2. Newtonsoft.Json序列化Enum类型

    [JsonConverter(typeof(StringEnumConverter))] public StringAlignment TextAlign { get => textAlign; ...

  3. win10和Ubuntu双系统安装过程中遇到的问题

    1.安装过程 注意分区问题,很重要 https://blog.csdn.net/baobei0112/article/details/77996570 https://blog.csdn.net/s7 ...

  4. APPLE-SA-2019-3-25-2 macOS Mojave 10.14.4,Security Update 2019-002 High Sierra, Security Update 2019-002 Sierra

    APPLE-SA-2019-3-25-2 macOS Mojave 10.14.4, Security Update2019-002 High Sierra, Security Update 2019 ...

  5. sql连接:inner join on, left join on, right join on使用详解

    点击打开原文 inner join(等值连接) 只返回两个表中联结字段相等的行 left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包 ...

  6. Mybatis(一)入门介绍

    一.MyBatis的发展 MyBatis 是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation迁移到google code, 并且改名M ...

  7. Django中session的基础了解

    基于cookie做用户验证时:敏感信息不适合放在cookie中 session依赖cookie session原理 cookie是保存在用户浏览器端的键值对 session是保存在服务器端的键值对 s ...

  8. python第二天,list和tuple

    概念:list是集合,且是可变集合,tuple是元组集合,不可变集合. 1.Python内置的一种数据类型是列表:list.list是一种有序的集合,可以随时添加和删除其中的元素. 主要知识点:初始化 ...

  9. zookeeperCli和Java操作zookeeperAPI

    推荐一个zookeeper可视化工具:zktools.exe eclipse集成的工具: http://www.massedynamic.org/eclipse/updates/ 1.zkCli客户端 ...

  10. WPF DataGrid 列显示0,-1(作废、删除)状态,1,2(支出、收入)类型,操作人(在其他表中),如何转换格式。

    操作人,左联,Join on letf //容我补充 状态,类型,类似的转换,在xmlns中引入common   xmlns:com="clr-namespace:XXX.Common&qu ...