HNOI2016 最小公倍数 题解
HNOI2016 最小公倍数 题解
很神秘的分块优化暴力。
首先有一个暴力的想法,每次取出所有
考虑对所有边按
我们考虑处理
考虑怎样满足
而对于当前块内同时满足
那么排序部分是
总复杂度应为
细节
-
对于连向同一连通块内的边,记得更新
。 -
记得询问和边都要排序。
-
由于有询问的
的情况,所以 的初值需要设为 。 -
如果是用指针扫询问,记得要把询问的
小于边权的 的询问过滤掉。
AC 代码:
const int N=1e5+5; const int B=448; int n,m; struct arr{ int u,v,a,b,num; void Read(){ return read(u,v,a,b); } }; int fa[N],sz[N]; int getfa(int x){ if(fa[x]==x)return x; return fa[x]=getfa(fa[x]); } int maxa[N],maxb[N]; void merge(int x,int y,int a,int b){ x=getfa(x),y=getfa(y); if(x==y){ maxa[x]=max(maxa[x],a); maxb[x]=max(maxb[x],b); return ; } if(sz[x]<sz[y])swap(x,y); maxa[x]=max(maxa[x],maxa[y]); maxb[x]=max(maxb[x],maxb[y]); maxa[x]=max(maxa[x],a); maxb[x]=max(maxb[x],b); sz[x]+=sz[y]; fa[y]=x; } arr e[N],q[N]; int Q; int ans[N]; int vis[N],bid; struct edge{ int v,a,b; }; vector<edge> g[N]; signed main(){ read(n,m); fo(i,1,m){ e[i].Read(); } sort(e+1,e+m+1,[](arr a,arr b){ return a.a<b.a; }); read(Q); fo(i,1,Q){ q[i].Read(); q[i].num=i; } sort(q+1,q+1+Q,[](arr a,arr b){ return a.a<b.a; }); int L=1; e[m+1].a=1e9+1; while(L<=Q&&q[L].a<e[1].a)++L; for(int l=1,r;l<=m;l=r+1){ r=min(m,l+B-1); sort(e+1,e+l,[](arr a,arr b){ return a.b<b.b; }); int R=L-1; while(R<Q&&q[R+1].a>=e[l].a&&q[R+1].a<=e[r].a&&q[R+1].a<e[r+1].a)++R; fo(i,1,n)fa[i]=i,sz[i]=1,maxa[i]=maxb[i]=-1; int t=1; sort(q+L,q+R+1,[](arr a,arr b){ return a.b<b.b; }); fo(i,L,R){ while(t<l&&e[t].b<=q[i].b){ merge(e[t].u,e[t].v,e[t].a,e[t].b); ++t; } vector<int> vec; fo(j,l,r){ if(e[j].a<=q[i].a&&e[j].b<=q[i].b){ int a=getfa(e[j].u),b=getfa(e[j].v); g[a].push_back({b,e[j].a,e[j].b}),g[b].push_back({a,e[j].a,e[j].b}),vec.push_back(a),vec.push_back(b); } } ++bid; queue<int> p; p.push(getfa(q[i].u)),vis[p.front()]=bid; int ma=-1,mb=-1,bz=0; while(p.size()){ int u=p.front(); p.pop(); if(u==getfa(q[i].v))bz=1; ma=max(ma,maxa[u]),mb=max(mb,maxb[u]); for(auto v:g[u]){ if(vis[v.v]!=bid){ vis[v.v]=bid; p.push(v.v); } ma=max(ma,v.a),mb=max(mb,v.b); } } if(bz&&ma==q[i].a&&mb==q[i].b)ans[q[i].num]=1; for(auto x:vec)g[x].clear(); } L=R+1; } fo(i,1,Q)if(ans[i])write("Yes\n"); else write("No\n"); return 0; }
分类:
杂项 / 分块 阈值分治
, 模拟赛 练习
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】