题意

题目链接

给出一张带权无向图,每次询问\((u, v)\)之间是否存在一条路径满足\(max(a) = A, max(b) = B\)

Sol

这题居然是分块。。想不到想不到。。做这题的心路历程大概可以写个800字的作文。

\(warning:\)下面的做法复杂度是错的。但是可以过

以下是attack的心路历程

考场上不会做,然后看了一眼题解发现可以对\(a\)分块。

怎么分呢?我们可以对边按\(a\)分块,然后把每个询问先按\(b\)排序后扔到对应的\(a\)所在的块内

这个时候\(b\)的限制就好搞了,每个块都是递增的,之前的块可以预处理之后排序,复杂度\(m\sqrt{m}\log m\)是可以接受的。

块内的呢?好像暴力就可以了,直接拿个启发式合并的可撤销带权并查集搞,维护一下路径最大值。复杂度也是\(m \sqrt{m} log m\),但是枚举的上界必须是\(M\)不然会wa(\(a\)相同\(b\)不相同),算了先交一发。。

然后交上去->80..

把T掉的数据下载下来发现居然有\(a\)全都相同的点。。。

emmmmmm,开始面向数据编程,每次询问的时候可以把每个块内询问\(a\)的最小值拿出来,按\(b\)排序之后双指针搞。

然后就过了,复杂度显然是不对的。只要来个\(a\)很小的数据就G了。

以下代码充满了attack对人生的思考,,,请谨慎观看

#include<bits/stdc++.h>
#define Pair pair<int, int>
#define MP(x, y) make_pair(x, y)
#define fi first
#define se second
//#define int long long
#define LL long long
#define Fin(x) {freopen(#x".in","r",stdin);}
#define Fout(x) {freopen(#x".out","w",stdout);}
using namespace std;
const int MAXN = 1e6 + 10, mod = 998244353, INF = 2e9 + 10;
const double eps = 1e-9;
template <typename A, typename B> inline bool chmin(A &a, B b){if(a > b) {a = b; return 1;} return 0;}
template <typename A, typename B> inline bool chmax(A &a, B b){if(a < b) {a = b; return 1;} return 0;}
template <typename A, typename B> inline LL add(A x, B y) {if(x + y < 0) return x + y + mod; return x + y >= mod ? x + y - mod : x + y;}
template <typename A, typename B> inline void add2(A &x, B y) {if(x + y < 0) x = x + y + mod; else x = (x + y >= mod ? x + y - mod : x + y);}
template <typename A, typename B> inline LL mul(A x, B y) {return 1ll * x * y % mod;}
template <typename A, typename B> inline void mul2(A &x, B y) {x = (1ll * x * y % mod + mod) % mod;}
template <typename A> inline void debug(A a){cout << a << '\n';}
template <typename A> inline LL sqr(A x){return 1ll * x * x;}
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, block, belong[MAXN], ll[MAXN], rr[MAXN], mx, ans[MAXN];
struct Edge {
int u, v, a, b, id;
bool operator < (const Edge &rhs) const {
return a == rhs.a ? b < rhs.b : a < rhs.a;
}
}E[MAXN], q[MAXN], st[MAXN], fuck1[MAXN];
vector<Edge> fuck2;
int comp(const Edge &x, const Edge &y) {
return x.b == y.b ? x.a < y.a : x.b < y.b;
}
vector<Edge> v[MAXN];
int vis[MAXN], num, fa[MAXN], mxa[MAXN], mxb[MAXN], siz[MAXN];
struct Sta {
int x, ta, tb, si;
};
Sta inst[MAXN];
int find(int x) {
return fa[x] == x ? x : find(fa[x]);
}
void Add(Edge &e) {
int x = e.u, y = e.v, a = e.a, b = e.b;
int fx = find(x), fy = find(y);
if(fx == fy) {
inst[++num] = {fx, mxa[fx], mxb[fx], siz[fx]};
inst[++num] = {fy, mxa[fy], mxb[fy], siz[fy]};
chmax(mxa[fx], a); chmax(mxb[fx], b);
return ;
}
if(siz[fx] > siz[fy]) swap(fx, fy), swap(x, y);
inst[++num] = {fx, mxa[fx], mxb[fx], siz[fx]};
inst[++num] = {fy, mxa[fy], mxb[fy], siz[fy]};
siz[fy] += siz[fx];
chmax(mxa[fy], a); chmax(mxb[fy], b);
chmax(mxa[fy], mxa[fx]); chmax(mxb[fy], mxb[fx]);
fa[fx] = fy;
}
void Erase(int tim) {
while(num > tim) {
Sta pre = inst[num--];
fa[pre.x] = pre.x; mxa[pre.x] = pre.ta; mxb[pre.x] = pre.tb; siz[pre.x] = pre.si;
}
} void solve() {
int top = 0;
for(int i = 1; i <= N; i++) fa[i] = i, siz[i] = 1, mxa[i] = mxb[i] = -1;
for(int i = 1; i <= mx; i++) {
int now = 1; int gg = num, fucknum = 0, mn = INF; fuck2.clear();
for(auto &x : v[i]) chmin(mn, x.a); for(int j = ll[i]; j <= M; j++)
if(E[j].a <= mn) fuck1[++fucknum] = E[j];
else fuck2.push_back(E[j]);
sort(fuck1 + 1, fuck1 + fucknum + 1, comp);
int cur = 0;
for(auto &x : v[i]) {
while(now <= top && st[now].b <= x.b) Add(st[now++]);
while(cur <= fucknum && fuck1[cur].b <= x.b) Add(fuck1[cur++]);
int tmp = num;
for(auto & j : fuck2) {
if(j.a <= x.a ) {
if(j.b <= x.b) {
Add(j);
}
} else break;
}
int fx = find(x.u), fy = find(x.v);
if(fx != fy || mxa[fx] != x.a || mxb[fx] != x.b) ans[x.id] = 2;
else ans[x.id] = 1;
Erase(tmp);
}
Erase(gg);
for(int j = ll[i]; j <= rr[i]; j++) st[++top] = E[j];
sort(st + 1, st + top + 1, comp);//�Ѿ�����İ�b�ź���ı�
} }
signed main() {
// Fin(a); Fout(b);
N = read(); M = read(); block = sqrt(M * log(M));
for(int i = 1; i <= M; i++) E[i].u = read(), E[i].v = read(), E[i].a = read(), E[i].b = read();
E[++M] = {-1, -1, INF, INF};
sort(E + 1, E + M + 1);
for(int i = 1; i <= M; i++) belong[i] = (i - 1) / block + 1, chmax(mx, belong[i]);
for(int i = 1; i <= mx; i++) ll[i] = (i - 1) * block + 1, rr[i] = min(M, ll[i] + block - 1);//tag
Q = read();
for(int i = 1; i <= Q; i++) q[i].u = read(), q[i].v = read(), q[i].a = read(), q[i].b = read(), q[i].id = i;
sort(q + 1, q + Q + 1, comp);
for(int i = 1; i <= Q; i++) {
int pos = lower_bound(E + 1, E + M + 1, q[i]) - E;
v[belong[pos]].push_back(q[i]);
}
solve();
for(int i = 1; i <= Q; i++) puts(ans[i] == 1 ? "Yes" : "No");
return 0;
}

洛谷P3247 [HNOI2016]最小公倍数(分块 带撤销加权并查集)的更多相关文章

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

    洛谷 思路 显然,为了达到这个最小公倍数,只能走\(a,b\)不是很大的边. 即,当前询问的是\(A,B\),那么我们只能走\(a\leq A,b\leq B\)的边. 然而,为了达到这最小公倍数,又 ...

  2. [洛谷P1196][NOI2002]银河英雄传说 - 带偏移量的并查集(1)

    Description 公元五八〇一年,地球居民迁至金牛座α第二行星,在那里发表银河联邦创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银河系的两大军事集团在巴米利恩星域爆发 ...

  3. 洛谷P2661 信息传递(最小环,并查集)

    洛谷P2661 信息传递 最小环求解采用并查集求最小环. 只适用于本题的情况.对于新加可以使得两个子树合并的边,总有其中一点为其中一棵子树的根. 复杂度 \(O(n)\) . #include< ...

  4. BZOJ4025: 二分图【线段树分治】【带撤销的并查集】

    Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简单的问题神犇当然会做了,于是他想考考你. Input ...

  5. 【洛谷 P3402】 【模板】可持久化并查集

    题目链接 可持久化并查集,就是用可持久化线段树维护每个版本每个节点的父亲,这样显然是不能路径压缩的,否则我们需要恢复太多状态. 但是这并不影响我们启发式合并,于是,每次把深度小的连通块向深度大的上并就 ...

  6. 洛谷P4698 [CEOI2011]Hotel [贪心,二分,并查集]

    题目传送门 Hotel 题目描述 你经营着一家旅馆,这家旅馆有 n 个房间,每个房间有维护费用和容量.其中第 i 个房间的维护费用为 ci​,容量为 pi​ 人. 现在有 m 个订单,每个订单有两个参 ...

  7. [洛谷P2024/POJ1182]食物链 - 带偏移量的并查集(2)

    Description 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的 ...

  8. [BZOJ 4025]二分图(线段树分治+带边权并查集)

    [BZOJ 4025]二分图(线段树分治+带边权并查集) 题面 给出一个n个点m条边的图,每条边会在时间s到t出现,问每个时间的图是否为一个二分图 \(n,m,\max(t_i) \leq 10^5\ ...

  9. Codevs 3287 货车运输 2013年NOIP全国联赛提高组(带权LCA+并查集+最大生成树)

    3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description A 国有 n 座 ...

随机推荐

  1. Spark基础-scala学习(八、隐式转换与隐式参数)

    大纲 隐式转换 使用隐式转换加强现有类型 导入隐式转换函数 隐式转换的发生时机 隐式参数 隐式转换 要实现隐式转换,只要程序可见的范围内定义隐式转换函数即可.Scala会自动使用隐式转换函数.隐式转换 ...

  2. PHP之ThinkPHP框架(会话)

    网页会话即是实现页面跳转及数据传递,在web开发中,Cookie和Session的使用是极其重要的,GET和POST是最常使用的页面间数据传递的方法,相对于PHP脚本基础,在ThinkPHP中对网页会 ...

  3. iOS学习——更改导航栏的返回按钮的标题与颜色

    转载自:修改navigationController返回按钮颜色和文字 今天在做项目时遇到这个问题,试了很多方法都失败了.最后终于找到正确的方案了,在这里分享给大家. 引言 在iOS开发过程中,Nav ...

  4. [原创]K8Cscan插件之Web主机扫描(存活主机、机器名、Banner、标题)

    [原创]K8 Cscan 大型内网渗透自定义扫描器 https://www.cnblogs.com/k8gege/p/10519321.html Cscan简介:何为自定义扫描器?其实也是插件化,但C ...

  5. 【MML】华为MML AAA接口联调,Java版本

    1.我们先设置一些常量数据 package cn.cutter.ztesoft.HuWeiMML.constrant; /** * @description: AAA接口常量设置 * @author: ...

  6. 冒泡 MS Azure 不便宜。。。

    一直在等 MS Azure 中国开卖, 最近有消息说正式商用了... 看看去,ok 发现官方网站 很奇葩.没有购买的地方 说毛线 啊 卧槽 欺骗感情还是吊人胃口? 好看了一下VM的价格,卧槽真不便宜. ...

  7. Git基本命令 -- 基本工作流程 + 文件相关操作

    可以先找一个已经被git管理的项目, 我就使用这个项目吧: https://github.com/solenovex/ID3-Editor 基本工作流程 克隆以后呢, 进入该目录查看一下状态: 然后添 ...

  8. 课程五(Sequence Models),第二 周(Natural Language Processing & Word Embeddings) —— 0.Practice questions:Natural Language Processing & Word Embeddings

    [解释] The dimension of word vectors is usually smaller than the size of the vocabulary. Most common s ...

  9. Java核心技术及面试指南 集合部分总的面试题归纳以及答案

    3.6.1ArrayList和LinkedList有什么差别?在哪种场景里应当用ArrayList(或LinkedList)? 大家如果学过数据结构,这个问题不难回答:前者是基于数组,数组比较擅长索引 ...

  10. Jexus使用的相关记录

    前言 本文是零零散散的记录,部分内容是我在平时工作中用到的,部分是从群里"偷"来的,所以难免会有一些错误. 主要还是希望能帮到部分使用Jexus的朋友. 安装 curl https ...