题目大意:

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

n,q <= 50000. m <= 100000

题解:

通过分析可以得到,我们能经过的所有的边的两种权一定均分别不大于给定的值.

把这些边称作可行边。那么我们把所有的可行边加入到图当中,然后判断询问的两个点是不是联通.

如果联通我们再进一步判断一下所有与其所在的联通块联通的所有边的两种边权的分别的最大值.

然后就是考虑如何快速统计出所有的边并将其加入到联通块中.

我们选择如下策略: 把所有的边按第一种权排序,然后分块.

每块内按照第二种权排序

事实证明上面划掉的方法直接TLE

我们考虑离线所有的操作,然后每次对第一种权在某一个块内的所有询问.

我们知道如果某个询问的第一种权在块i中,那么1 ~ i-`中的所有边的第一种权都符合条件.

所以这时候对1 ~ i-1块中的所有边按照第二种权排序.

如果我们处理询问的时候按照第二种权递增访问就可以做到线性统计了.

所以我们将所有此时应该处理的询问按照第二种权排序.

那么我们可以线性统计所有在1 ~ i-1块中的边完成所有此时的询问.

那么在第i个块中的呢 ?

直接暴力查询,然后维护可持久化并查集即可.

我们直接记录所有的操作,然后暴力撤销即可.

不要问我复杂度是多少,O(跑的过)

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define rg register int
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 100010;
const int maxm = 100010;
struct Edge{
int id;
int u,v,a,b;
}e[maxm],q[maxm],tmp[maxm];
int cnt;
inline bool cmpa(const Edge &a,const Edge &b){
return a.a == b.a ? a.b < b.b : a.a < b.a;
}
inline bool cmpb(const Edge &a,const Edge &b){
return a.b == b.b ? a.a < b.a : a.b < b.b;
}
int n,m;
struct Node{
int idx,idy,fa,siz,mxa,mxb;
Node(){}
Node(const int &a,const int &b,const int &c
,const int &d,const int &e,const int &f){
idx = a;idy = b;fa = c;siz = d;mxa = e;mxb = f;
}
}sta[maxm];
int top;
int fa[maxn],siz[maxn],mxa[maxn],mxb[maxn];
inline void clear(){
for(int i=1;i<=n;++i){
fa[i] = i;siz[i] = 1;
mxa[i] = mxb[i] = -1;
}
}
inline int find(int x){
while(x != fa[x]) x = fa[x];
return x;
}
inline void Union(const Edge &e){
int x = find(e.u),y = find(e.v);
if(siz[x] > siz[y]) swap(x,y);
sta[++top] = Node(x,y,fa[x],siz[y],mxa[y],mxb[y]);
mxa[y] = max(mxa[y],max(mxa[x],e.a));
mxb[y] = max(mxb[y],max(mxb[x],e.b));
if(x == y) return ;
siz[y] += siz[x];fa[x] = y;
}
inline void Undo(){
while(top){
fa[sta[top].idx] = sta[top].fa;
siz[sta[top].idy] = sta[top].siz;
mxa[sta[top].idy] = sta[top].mxa;
mxb[sta[top].idy] = sta[top].mxb;
-- top;
}
}
bool ans[maxm];
int main(){
read(n);read(m);
for(int i=1;i<=m;++i){
read(e[i].u);read(e[i].v);
read(e[i].a);read(e[i].b);
}
int Q;read(Q);
for(int i=1;i<=Q;++i){
read(q[i].u);read(q[i].v);
read(q[i].a);read(q[i].b);
q[i].id = i;
}
sort(e+1,e+m+1,cmpa);sort(q+1,q+Q+1,cmpb);
int block = sqrt(m);
for(int i=1;i<=m;i+=block){
cnt = 0;
for(int j=1;j<=Q;++j){
if(q[j].a >= e[i].a && (i+block > m || e[i+block].a > q[j].a)){
tmp[++cnt] = q[j];
}
}
sort(e+1,e+i,cmpb);clear();
for(int j=1,k=1;j<=cnt;++j){
while(k < i && e[k].b <= tmp[j].b) Union(e[k++]);
top = 0;
for(int l=i;l<i+block && l <= m;++l){
if(e[l].a <= tmp[j].a && e[l].b <= tmp[j].b) Union(e[l]);
}
int x = find(tmp[j].u),y = find(tmp[j].v);
if(x == y && mxa[x] == tmp[j].a && mxb[x] == tmp[j].b) ans[tmp[j].id] = true;
Undo();
}
}
for(int i=1;i<=Q;++i) puts(ans[i] ? "Yes" : "No");
return 0;
}

其实复杂度是:\(O( m\sqrt{m}logm + q(logn+logq))\)的

bzoj 4537: [Hnoi2016]最小公倍数 分块+并查集的更多相关文章

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

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

  2. BZOJ 4537: [Hnoi2016]最小公倍数 [偏序关系 分块]

    4537: [Hnoi2016]最小公倍数 题意:一张边权无向图,多组询问u和v之间有没有一条a最大为a',b最大为b'的路径(不一定是简单路径) 首先想到暴力做法,题目要求就是判断u和v连通,并查集 ...

  3. bzoj 4537 HNOI2016 最小公倍数

    Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,-,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在有q个询问,每次询问给定四个参数u.v.a和b,请你 ...

  4. 洛谷P3247 最小公倍数 [HNOI2016] 分块+并查集

    正解:分块+并查集 解题报告: 传送门! 真的好神仙昂QAQ,,,完全想不出来,,,还是太菜了QAQ 首先还是要说下,这题可以用K-D Tree乱搞过去(数据结构是个好东西昂,,,要多学学QAQ),但 ...

  5. BZOJ.2054.疯狂的馒头(并查集)

    BZOJ 倒序处理,就是并查集傻题了.. 并查集就是确定下一个未染色位置的,直接跳到那个位置染.然而我越想越麻烦=-= 以为有线性的做法,发现还是要并查集.. 数据随机线段树也能过去. //18400 ...

  6. [APIO2019] [LOJ 3145] 桥梁(分块+并查集)(有详细注释)

    [APIO2019] [LOJ 3145] 桥梁(分块+并查集)(有详细注释) 题面 略 分析 考试的时候就感觉子任务4是突破口,结果却写了个Kruskal重构树,然后一直想怎么在线用数据结构维护 实 ...

  7. P5443 [APIO2019]桥梁 [分块+并查集]

    分块+并查集,大板子,没了. 并查集不路径压缩,可撤销,然后暴力删除 这样对于每个块都是独立的,所以直接搞就行了. 然后块内修改操作搞掉,就是单独的了 // powered by c++11 // b ...

  8. 2021.08.03 BZOJ 疯狂的馒头(并查集)

    2021.08.03 BZOJ 疯狂的馒头(并查集) 疯狂的馒头 - 题目 - 黑暗爆炸OJ (darkbzoj.tk) 重点: 1.并查集的神奇运用 2.离线化 题意: 给一个长为n的序列,进行m次 ...

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

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

随机推荐

  1. 解决不同浏览器创建不同 XMLHTTP 对象的问题

    function GetXmlHttpObject() { var xmlHttp=null; try { // Firefox, Opera 8.0+, Safari xmlHttp=new XML ...

  2. 安装部署服务器和javaweb项目

    [说明]总算告一段落了,服务器啊服务器,你可是把我折磨的够呛,不过现在的状态我已经很满足了. [说明]下面的图片是我这两天一直在搞的,内容不能说是重复,只能说是不停地修改修改,出错出错. 1) 虚拟主 ...

  3. 序列DP(输出有要求)

    DP Time Limit:10000MS     Memory Limit:165888KB     64bit IO Format:%lld & %llu Submit Status De ...

  4. vscode 和 atom 全局安装和配置 eslint 像 webstorm 等 ide 一样使用 standard标准 来检查项目

    首先你要安装了 nodejs ,然后在终端命令行输入下面的这堆 npm install eslint eslint-plugin-standard eslint-config-standard esl ...

  5. 解决Eclipse的Team菜单中没有SVN选项的问题

    我们想使用SVN向SVN服务器上传代码,但Eclipse默认情况下却没有SVN选项,如下图所示. 默认只有GIT,如下图所示. 那么,我们怎么解决这个问题呢? 第一步:如下图所示. 第二步:在&quo ...

  6. hdu 2036 改革春风吹满地【求多边形面积模板】

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=2036 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  7. git生成public key

    1 配置user name和email git config --global user.name "xxx" git config --global user.email &qu ...

  8. iOS解决导航引起视图高度问题

    经过导航栏跨越的坑,总结出有两种方法可以无痕解决(前提>=iOS7版本)(TabBar与导航栏类似) 1.通过设置导航栏的透明度实现(这种方式的控制器view的起始坐标是充(0,64)开始的) ...

  9. 通过Safari获取iOS设备的UUID,远程发送更是便捷

    1.获取UUID (1)在Safari上输入:http://fir.im/udid (2)点击安装描述文件,然后就可以获取到UUID了 2.fir.im提供一个非常好用的内侧平台 详情使用见:http ...

  10. height为auto, 滚动条出现时, 使页面不跳动

    <style> html { margin-left: calc(100vw - 100%); } </style> ;