题目大意:

给定一张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. .net EF监控 MiniProfiler

    1.从NuGet上下载所需要的包:MiniProfiler.mvc,MiniProfiler,MiniProfiler.ef 2.Global.asax 加入 protected void Appli ...

  2. PAT 1063. 计算谱半径(20)

    在数学中,矩阵的“谱半径”是指其特征值的模集合的上确界.换言之,对于给定的n个复数空间的特征值{a1+b1i, ..., an+bni},它们的模为实部与虚部的平方和的开方,而“谱半径”就是最大模. ...

  3. 016-Spring Boot JDBC

    一.数据源装配 通过查看代码可知,默认已装配了数据源和JdbcTemplate System.out.println(context.getBean(DataSource.class)); Syste ...

  4. MySQL一些常见查询方式

    1.查询端口号命令: show global variables like 'port'; 2.查看版本号: select version(); 3.查看默认安装的MySQL的字符集 show var ...

  5. 中国移动OneNet平台上传GPS数据JSON格式

    最终目的输出 POST /devices/3225187/datapoints HTTP/1.1 api-key: R9xO5NZm6oVI4YBHvCPKEqtwYtMA Host: api.hec ...

  6. wap网站即手机端网页SEO优化注意事项及方法

    定位和页面设计: 无论是PC端还是移动端,网站 都要考虑清楚消费群体的定位问题.虽然智能手机用户数量非常普及,但是要明白中国的大部分手机用户使用的还是2G网络,一直高 喊的3G.4G手机用户只有大约1 ...

  7. 为什么要用redux?component自身管理自己的state难道不更解耦吗?

    这是前几天百度2面的时候,面试官问我的一个问题.说实话当时有点紧张,其实也没去细想,本身react我就学了2个多星期,虽然看过redux这些源码,不过这个问题好像我从来没想过. 那其实react官网本 ...

  8. nginx 启动/停止/重启

    启动: -c filename   : set configuration file (default: conf/nginx.conf) [root@LinuxServer sbin]# /usr/ ...

  9. Spring 相关

    1. spring的bean的scope属性范围  参考:http://jiangshuiy.iteye.com/blog/1667316 原理分析(bean的scope属性范围) scope用来声明 ...

  10. 织梦dedecms 无法下载远程图片 fsockopen函数被禁用的解决方法

    在linux服务器上fsockopen()函数被无情的禁用了(这其实是出于安全考虑,可以理解),下载远程图片的功能就没有办法使用了.找了一些资料之后,找到了解决方法,就是用stream_socket_ ...