BZOJ 4537: [Hnoi2016]最小公倍数 [偏序关系 分块]
4537: [Hnoi2016]最小公倍数
题意:一张边权无向图,多组询问u和v之间有没有一条a最大为a',b最大为b'的路径(不一定是简单路径)
首先想到暴力做法,题目要求就是判断u和v连通,并查集把\(a<a' \land b<b'\)的边加入
然后想了一下特殊的莫队,不可做。不能按权值分块,因为同一个权值会有很多边,并且删除操作不好处理
发现这其实是一个偏序关系,但是无法用cdq分治,因为它要求所有满足偏序小的元素同时存在于某种组织形式中
使用分块
权值用\((a,b)\)表示
边按a排序,然后分块。对于每一块i,处理a'在这一块中的询问。这时候之前块的\(a<a'\)这一个关系一定满足,按b排序后也满足\(b<b'\)了
块i中还有一些满足的,最多\(\sqrt{m}\) 暴力加入然后撤销就可以了
不路径压缩的并查集,启发式合并的话复杂度log
注意是边权
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=2e5+5;
inline int read(){
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
int n, m, Q, u, v, x, y, block, bn, top, ans[N];
struct meow {
int u, v, a, b, id;
inline void print() {printf("%d %d %d %d\n", u, v, a, b);}
} e[N], q[N], a[N];
inline bool cmpa(const meow &a, const meow &b) {return a.a == b.a ? a.b < b.b : a.a < b.a;}
inline bool cmpb(const meow &a, const meow &b) {return a.b == b.b ? a.a < b.a : a.b < b.b;}
namespace ufs {
struct meow{int fa, maxa, maxb, size;} t[N];
struct info{int x, y; meow a, b; } st[N];
inline int find(int x) {return x == t[x].fa ? x : find(t[x].fa);}
inline void ini() {for(int i=1; i<=n; i++) t[i] = (meow){i, -1, -1, 1}; }
inline void link(int id) { //printf("link %d\n", id);
int x = find(e[id].u), y = find(e[id].v);
st[++top] = (info){x, y, t[x], t[y]};
if(x==y) {
t[x].maxa = max(t[x].maxa, e[id].a);
t[x].maxb = max(t[x].maxb, e[id].b);
return;
}
if(t[x].size < t[y].size) swap(x, y);
t[y].fa = x;
t[x].maxa = max(max(t[y].maxa, t[x].maxa), e[id].a);
t[x].maxb = max(max(t[y].maxb, t[x].maxb), e[id].b);
t[x].size += t[y].size;
}
inline void recov() {
t[ st[top].x ] = st[top].a, t[ st[top].y ] = st[top].b;
top--;
}
inline bool check(int id) {
int x = find(a[id].u), y = find(a[id].v);
//printf("check %d %d %d %d %d %d\n", id, x, y, t[x].maxa, t[x].maxb, t[x].size);
return x == y && t[x].maxa == a[id].a && t[x].maxb == a[id].b;
}
} using ufs::st;
void solve() {
sort(e+1, e+m+1, cmpa); sort(q+1, q+Q+1, cmpa);
block = sqrt(m); bn = (m-1)/block+1;
for(int i=1; i<=bn; i++) { //printf("\n---------- %d\n", i);
int l = (i-1)*block+1, r = i==bn ? m : i*block; //printf("[%d, %d]\n", l, r);
int p=0;
for(int i=1; i<=Q; i++)
if(q[i].a >= e[l].a && (r==m || q[i].a < e[r+1].a) ) a[++p] = q[i];
sort(e+1, e+l, cmpb); sort(a+1, a+p+1, cmpb);
//for(int i=1; i<=p; i++) a[i].print();
int now=1;
ufs::ini();
for(int i=1; i<=p; i++) {
while(now < l && e[now].b <= a[i].b) ufs::link(now), now++;
top=0;
for(int j=l; j<=r; j++)
if(e[j].a <= a[i].a && e[j].b <= a[i].b) ufs::link(j);// printf("j %d\n", j);
ans[ a[i].id ] = ufs::check(i);
while(top) ufs::recov();
}
}
for(int i=1; i<=Q; i++) puts(ans[i] ? "Yes" : "No");
}
int main() {
//freopen("in", "r", stdin);
freopen("multiple.in", "r", stdin);
freopen("multiple.out", "w", stdout);
n=read(); m=read();
for(int i=1; i<=m; i++) u=read(), v=read(), x=read(), y=read(), e[i] = (meow){u, v, x, y, i};
Q=read();
for(int i=1; i<=Q; i++) u=read(), v=read(), x=read(), y=read(), q[i] = (meow){u, v, x, y, i};
solve();
}
BZOJ 4537: [Hnoi2016]最小公倍数 [偏序关系 分块]的更多相关文章
- bzoj 4537: [Hnoi2016]最小公倍数 分块+并查集
题目大意: 给定一张n个点m条边的无向图,每条边有两种权.每次询问某两个点之间是否存在一条路径上的边的两种权的最大值分别等于给定值. n,q <= 50000. m <= 100000 题 ...
- bzoj 4537 HNOI2016 最小公倍数
Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,-,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在有q个询问,每次询问给定四个参数u.v.a和b,请你 ...
- 4537: [Hnoi2016]最小公倍数
Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,…,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在有q个询问,每次询问给定四个参数u.v.a和b,请你 ...
- [BZOJ4537][HNOI2016]最小公倍数(分块+并查集)
4537: [Hnoi2016]最小公倍数 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1687 Solved: 607[Submit][Stat ...
- [BZOJ4537][Hnoi2016]最小公倍数 奇怪的分块+可撤销并查集
4537: [Hnoi2016]最小公倍数 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1474 Solved: 521[Submit][Stat ...
- 【BZOJ4537】[Hnoi2016]最小公倍数 分块
[BZOJ4537][Hnoi2016]最小公倍数 Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,…,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在 ...
- 【LG3247】[HNOI2016]最小公倍数
[LG3247][HNOI2016]最小公倍数 题面 洛谷 题解 50pts 因为拼凑起来的部分分比较多,所以就放一起了. 以下设询问的\(a,b\)为\(A,B\), 复杂度\(O(nm)\)的:将 ...
- BZOJ 3343: 教主的魔法(分块+二分查找)
BZOJ 3343: 教主的魔法(分块+二分查找) 3343: 教主的魔法 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1172 Solved: ...
- [BZOJ 3509] [CodeChef] COUNTARI (FFT+分块)
[BZOJ 3509] [CodeChef] COUNTARI (FFT+分块) 题面 给出一个长度为n的数组,问有多少三元组\((i,j,k)\)满足\(i<j<k,a_j-a_i=a_ ...
随机推荐
- 微信小程序模板消息详解
先放代码 wxml: <form name='pushMsgFm' report-submit bindsubmit='orderSign'> <view> 单号: 0< ...
- word文档自动生成方法
创建word文档需要几个接口类,常用application,document,documents,selection等.但word的功能复杂,要认识到每一个类的功能是不可能的.常用的方法是在word的 ...
- [学习OpenCV攻略][007][缩小图片]
cvPryDown(输入图片,输出图片) 根据输出图片的大小,把输入图片进行压缩 cvPryUp(输入图片,输出图片) 根据输出图片的大小,把输入图片进行放大 #include "cv.h& ...
- 自己实现一个each迭代器
什么是迭代器? 其实就是对一个对象内部进行遍历的方法,比如jquery的each方法,或者原生js的foreach方法. 迭代器的特点 针对迭代器,这里有几个特点: ☑ 访问一个聚合对象的内容而无需暴 ...
- FTP下载导致Zip解压失败的原因
情形:网关通过FTP下载快钱对账文件时通过Apache下commons-net的commons-net-3.5.jar进行封装,对账文件中有中文和英文的文字,大部分情况下能够下载成功,而且也能解压成功 ...
- 在阿里云服务器上安装完成并启动Tomcat后,通过http不能访问--解决办法
在阿里云服务器上安装完成并启动Tomcat后,通过http不能访问的原因是阿里云平台为了安全设置了安全组策略,必须我们授权的端口,其他计算机才能通过http访问 解决办法:(这里以阿里轻量应用服务器为 ...
- iOS学习——键盘弹出遮挡输入框问题解决方案
在iOS或Android等移动端开发过程中,经常遇到很多需要我们输入信息的情况,例如登录时要输入账号密码.查询时要输入查询信息.注册或申请时需要填写一些信息等都是通过我们键盘来进行输入的,在iOS开发 ...
- tp系统常量定义
(2013-03-06 14:16:31) 转载▼ 标签: it 是已经封装好的系统常量 主要是用在控制器下面的动作当中 这样能很大的提高我们的开发效率 主要有下面的一些 手册上面都有的 ...
- DEDECMS开启邮箱验证通知的解决方法
[摘要]织梦CMS是开源内容管理系统,是国内开源CMS的领先品牌,目前程序安装量已达七十万,本文介绍DEDECMS会员注册时,开启邮箱验证通知的解决方法. 在论坛上看到很多人都说这个功能没用,邮箱根本 ...
- 随手小代码——《Python编程 从入门到实践》项目1:外星人入侵
=================================版权声明================================= 版权声明:原创文章 禁止转载 请通过右侧公告中的“联系邮 ...