loj2048 「HNOI2016」最小公倍数
题意:
给定一张$N$个顶点$M$条边的无向图(顶点编号为$1,2,...,n$),每条边上带有权值。所有权值都可以分解成$2^a \cdot 3^b$的形式。
现在有$q$个询问,每次询问给定$u,v,a,b$,请你求出是否存在一条顶点$u$到$v$之间的路径,使得路径依次经过的边上的权值的最小公倍数为$2^a \cdot 3^b$?路径可以不是简单路径。
$n,q\leq 5\times 10^4,m\leq 10^5.$
题解:
我们用qx,qy,qa,qb表示询问中的x,y,a,b,ex,ey,ea,eb表示某条边的x,y,a,b。
如何处理一个询问?将ea,eb分别小于等于qa,qb的边连接起来,若满足qx,qy连通且$\max\{ea\}=qa\&\&\max\{eb\}=qb$,则答案为Yes,否则为No。可以用并查集维护。
多个询问怎么办呢?离线。
一个分块的思路,将a分成若干块,每次处理a在当前块范围内的询问。首先询问按照b排序,对于一个询问qa,qb,我们要找所有$ea\leq qa\&\& eb\leq qb$的边,把它们连起来。
设当前块a的范围为$[L,R)$,两种情况:
- $ea<L$,将ea在$[1,L)$的边按eb排序,那么只要扫过去就行了;
- $L\leq ea<R$,暴力枚举合法的边插入,然后暴力退回,用一个栈维护要退回的信息;
使用无路径压缩并查集按秩合并即可。
复杂度$\mathcal{O}(\sqrt{m}(n+q\log n))$。
code:
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#define rep(i,x,y) for (register int i=(x);i<=(y);i++)
using namespace std;
char gc(){
static char buf[],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,,,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){
char ch=gc(); register int x=;
for (;!isdigit(ch);ch=gc());
for (;isdigit(ch);ch=gc()) x=x*+ch-;
return x;
}
const int N=1e5+;
int n,m,Q,blo,top,x,y,sz,a,b,fa[N],mxa[N],mxb[N],siz[N]; bool ans[N];
struct node{
int x,y,a,b,id;
void rd(){ x=read(),y=read(),a=read(),b=read(); }
node(){} node(int _x,int _y,int _a,int _b,int _id){ x=_x,y=_y,a=_a,b=_b,id=_id; }
}e[N],q[N],nq[N],stk[N];
inline void up(register int &x,register int y){ x=max(x,y); }
inline bool cmp_a(const node &x,const node &y){ return x.a<y.a||x.a==y.a&&x.b<y.b; }
inline bool cmp_b(const node &x,const node &y){ return x.b<y.b||x.b==y.b&&x.a<y.a; }
inline int getfa(register int x){ return x==fa[x]?x:getfa(fa[x]); }
inline void mer(register int x,register int y,register int a,register int b){
x=getfa(x),y=getfa(y);
if (siz[x]>siz[y]) swap(x,y);
stk[++top].x=x; stk[top].y=y; stk[top].a=mxa[y]; stk[top].b=mxb[y]; stk[top].id=siz[y];
if (x!=y) fa[x]=y,siz[y]+=siz[x],up(mxa[y],mxa[x]),up(mxb[y],mxb[x]);
up(mxa[y],a); up(mxb[y],b);
}
int main(){
n=read(),m=read();
rep (i,,m) e[i].rd();
sort(e+,e++m,cmp_a); e[m+].a=1e9;
Q=read();
rep (i,,Q) q[i].rd(),q[i].id=i;
sort(q+,q++Q,cmp_b);//事先将询问按照b排序,方便之后处理
for (register int L=,R,Top,blo=sqrt(*m);L<=m;L+=blo){//按照a分为sqrt个块
R=min(L+blo,m+); Top=top=;
rep (i,,n) fa[i]=i,mxa[i]=mxb[i]=-,siz[i]=;
rep (i,,Q)//提取a在当前块的询问
if (e[L].a<=q[i].a&&q[i].a<e[R].a) nq[++Top]=q[i];
if (!Top) continue;
if (L>) sort(e+,e+L,cmp_b);//a<当前块的边按照b排序
for (register int i=,j=;i<=Top;i++){
for (;j<L&&e[j].b<=nq[i].b;j++)//插入a<当前块的边
mer(e[j].x,e[j].y,e[j].a,e[j].b);
top=;
rep (k,L,R)
if (e[k].a<=nq[i].a&&e[k].b<=nq[i].b)//插入当前块的合法边
mer(e[k].x,e[k].y,e[k].a,e[k].b);
x=getfa(nq[i].x),y=getfa(nq[i].y);
ans[nq[i].id]|=x==y&&mxa[x]==nq[i].a&&mxb[x]==nq[i].b;
for (;top;top--){//退回
x=stk[top].x,y=stk[top].y;
fa[x]=x; siz[y]=stk[top].id;
mxa[y]=stk[top].a; mxb[y]=stk[top].b;
}
}
}
rep (i,,Q) puts(ans[i]?"Yes":"No");
return ;
}
易错:
没错你会发现我代码里的明显卡常痕迹。。。
艰辛卡常后的我……发现一个致命的错误:“提取a在当前块的询问”这部分,必须写q[i].a<e[R].a,不能改成q[i].a<=e[R-1].a。
考虑一种极端情况,所有边和询问的a全相等,时间复杂度直接退化成$n^2$。
loj2048 「HNOI2016」最小公倍数的更多相关文章
- 「HNOI2016」最小公倍数 解题报告
「HNOI2016」最小公倍数 考虑暴力,对每个询问,处理出\(\le a,\le b\)的与询问点在一起的联通块,然后判断是否是一个联通块,且联通块\(a,b\)最大值是否满足要求. 然后很显然需要 ...
- 「HNOI2016」最小公倍数
链接 loj 一道阔爱的分块 题意 边权是二元组(A, B),每次询问u, v, a, b,求u到v是否存在一条简单路径,使得各边权上\(A_{max} = a, B_{max} = b\) 分析 对 ...
- LOJ #2048. 「HNOI2016」最小公倍数
题意 有 \(n\) 个点,\(m\) 条边,每条边连接 \(u \Leftrightarrow v\) 且权值为 \((a, b)\) . 共有 \(q\) 次询问,每次询问给出 \(u, v, q ...
- 「HNOI2016」数据结构大毒瘤
真是 \(6\) 道数据结构毒瘤... 开始口胡各种做法... 「HNOI2016」网络 整体二分+树状数组. 开始想了一个大常数 \(O(n\log^2 n)\) 做法,然后就被卡掉了... 发现直 ...
- 「HNOI2016」树 解题报告
「HNOI2016」树 事毒瘤题... 我一开始以为每次把大树的子树再接给大树,然后死活不知道咋做,心想怕不是个神仙题哦 然后看题解后才发现是把模板树的子树给大树,虽然思维上难度没啥了,但是还是很难写 ...
- 「HNOI2016」序列 解题报告
「HNOI2016」序列 有一些高妙的做法,懒得看 考虑莫队,考虑莫队咋移动区间 然后你在区间内部找一个最小值的位置,假设现在从右边加 最小值左边区间显然可以\(O(1)\),最小值右边的区间是断掉的 ...
- 「HNOI2016」网络 解题报告
「HNOI2016」网络 我有一个绝妙的可持久化树套树思路,可惜的是,它的空间是\(n\log^2 n\)的... 注意到对一个询问,我们可以二分答案 然后统计经过这个点大于当前答案的路径条数,如果这 ...
- loj #2051. 「HNOI2016」序列
#2051. 「HNOI2016」序列 题目描述 给定长度为 n nn 的序列:a1,a2,⋯,an a_1, a_2, \cdots , a_na1,a2,⋯,an,记为 a[1: ...
- 【LOJ】#2052. 「HNOI2016」矿区
题解 之前尝试HNOI2016的时候弃坑的一道,然后给补回来 (为啥我一些计算几何就写得好长,不过我写啥都长orz) 我们尝试给这个平面图分域,好把这个平面图转成对偶图 怎么分呢,我今天也是第一次会 ...
随机推荐
- 分布式锁--Redis小试牛刀
参考文章: Redis分布式锁的正确实现方式 分布式锁看这篇就够了 在这两篇文章的指引下亲测 Redis分布式锁 引言 分布式系统一定会存在CAP权衡问题,所以才会出现分布式锁 什么是CAP理论? 为 ...
- bzoj千题计划265:bzoj4873: [六省联考2017]寿司餐厅
http://www.lydsy.com/JudgeOnline/problem.php?id=4873 选a必选b,a依赖于b 最大权闭合子图模型 构图: 1.源点 向 正美味度区间 连 流量为 美 ...
- B-树(B+树) 学习总结
一,B-树的定义及介绍 为什么会有B-树? 熟悉的树的结构有二叉树查找树或者平衡二叉树……平衡二叉树保证最坏情况下各个操作的时间复杂度为O(logN),但是为了保持平衡,在插入或删除元素时,需要进行旋 ...
- js 奇葩技巧之隐藏代码
昨天在群看到有人发了个文章叫<“短”化你的代码>,思路非常不错,采用unicode的零宽字符来实现字符隐藏,虽然有字符,可是你却看不见它.这篇文章详细的介绍了这种方法的实现原理,最后还给出 ...
- js调试系列: 初识控制台
写在最开头:其实我以前就在考虑要不要写这个东西,因为这个东西确实不难,但是为什么会有这么多人问,他们问的不是怎么用控制台,而是不知道控制台能干嘛,他们也知道有 console.log 之类的东西,但他 ...
- Web性能优化系列(3):如何延迟加载JS
本文由 伯乐在线 - J.c 翻译,sunbiaobiao 校稿.未经许可,禁止转载!英文出处:www.feedthebot.com.欢迎加入翻译小组. 延迟加载JavaScript JavaScri ...
- Linux 网卡流量查看
网卡流量查看 watch more /proc/net/dev # 实时监控流量文件系统 累计值 iptraf # 网卡流量查看工具 nethogs -d 5 eth0 eth1 # 按进程实时统计网 ...
- C# 常用控件属性及方法介绍
C#常用控件属性及方法介绍 目录 1.窗体(Form) 2.Label (标签)控件 3.TextBox ...
- (FFT)A+B Problem
题目链接:https://cn.vjudge.net/contest/280041#problem/B 题目大意:给你n个数,然后让你找满足a[i] + a[j] = a[k] 的情况总数. 具体思路 ...
- TCP/UDP区别&&心跳包机制【转】
转自:https://www.jianshu.com/p/6d93a3c21c34 UDP:用户数据报协议:主要用在实时性要求比较高的以及对质量相对较弱的地方.但是面对现在高质量的线路不会容易丢包,除 ...