题面

给一个

N

N

N 点

M

M

M 边的简单无向图,询问

Q

Q

Q 次,每次问你把编号在

[

l

i

,

r

i

]

[l_i,r_i]

[li​,ri​] 之间的边删掉后,该图是否存在奇数环,即是否不能被二染色

1

N

,

M

,

Q

200000

1\leq N,M,Q\leq 200000

1≤N,M,Q≤200000.

题解

看了半天才搞懂官解里的奇怪分治是什么,其实就是整体二分嘛!

部分分就不多赘述了,大概就是一步步引导我们到正解的整体二分+可回退并查集(官解称其为:DSU)上。

并查集是经典的解决二染色问题的方法了,每个点存一个值表示自己和父亲的颜色是否不同(0/1),再存一个集合大小,然后用启发式合并保证每次只变动一条边,最后用一个栈来存每次加的边,以备回退之需。

我们发现答案具有包含性,即:若询问为

[

l

,

r

]

[l,r]

[l,r] 时答案是 YES,那么

[

l

,

r

]

[l',r']

[l′,r′] (

[

l

,

r

]

[

l

,

r

]

[l',r']\sub[l,r]

[l′,r′]⊂[l,r])的答案也是 YES ,这个易证,因为能形成奇数环的边都还在。

再换一种思路,我们令

m

a

x

r

[

i

]

maxr[i]

maxr[i] 为区间左端点 l=i+1满足答案是 YES 的最大右端点编号 +1(即此时

[

1

,

i

]

[

m

a

x

r

[

i

]

,

M

]

[1,i]\cup[maxr[i],M]

[1,i]∪[maxr[i],M] 以内的边都保留)。那么对于一个询问

[

l

,

r

]

[l,r]

[l,r] 当且仅当

m

a

x

r

[

l

1

]

>

r

maxr[l-1]>r

maxr[l−1]>r 时答案为 YES。同时,由于之前的包含性,我们可以发现

i

<

j

m

a

x

r

[

i

]

m

a

x

r

[

j

]

i<j\Rightarrow maxr[i]\leq maxr[j]

i<j⇒maxr[i]≤maxr[j]

即:

m

a

x

r

[

i

]

maxr[i]

maxr[i] 单调不降!

为了配合可回退并查集,具体地,我们这样分治:

  1. s

    o

    l

    v

    e

    (

    l

    1

    ,

    r

    1

    ,

    l

    2

    ,

    r

    2

    )

    solve(l_1,r_1,l_2,r_2)

    solve(l1​,r1​,l2​,r2​),四个参数,分别表示两个区间:要求的标号区间

    [

    l

    1

    ,

    r

    1

    ]

    [l_1,r_1]

    [l1​,r1​],以及通过之前的计算已经确定的该区间内针对所有位置

    m

    a

    x

    r

    maxr

    maxr 的范围

    [

    l

    2

    ,

    r

    2

    ]

    [l_2,r_2]

    [l2​,r2​]。为配合并查集,操作前得保证前提条件

    l

    1

    l_1

    l1​ 左边的边和

    r

    2

    r_2

    r2​ 右边的边都已经加入并查集。

  2. 整体二分常规程序,先取

    m

    i

    d

    1

    =

    l

    1

    +

    r

    1

    2

    mid_1=\lfloor\frac{l_1+r_1}{2}\rfloor

    mid1​=⌊2l1​+r1​​⌋,然后把

    [

    l

    1

    ,

    m

    i

    d

    1

    ]

    [l_1,mid_1]

    [l1​,mid1​] 的边都加上,再从

    r

    2

    r_2

    r2​ 开始往前加边,直到存在奇数环,即求出了

    m

    a

    x

    r

    [

    m

    i

    d

    1

    ]

    maxr[mid_1]

    maxr[mid1​]。

  3. m

    i

    d

    2

    =

    m

    a

    x

    r

    [

    m

    i

    d

    1

    ]

    mid_2=maxr[mid_1]

    mid2​=maxr[mid1​],那么我们可以往下转移了,我们知道

    [

    l

    1

    ,

    m

    i

    d

    1

    1

    ]

    [l_1,mid_1-1]

    [l1​,mid1​−1] 的

    m

    a

    x

    r

    maxr

    maxr 一定在

    [

    l

    2

    ,

    m

    i

    d

    2

    ]

    [l_2,mid_2]

    [l2​,mid2​] 以内,以及

    [

    m

    i

    d

    1

    +

    1

    ,

    r

    1

    ]

    [mid_1+1,r_1]

    [mid1​+1,r1​] 的

    m

    a

    x

    r

    maxr

    maxr 一定在

    [

    m

    i

    d

    2

    ,

    r

    2

    ]

    [mid_2,r_2]

    [mid2​,r2​] 以内。

  4. 递归

    s

    o

    l

    v

    e

    (

    m

    i

    d

    1

    +

    1

    ,

    r

    1

    ,

    m

    i

    d

    2

    ,

    r

    2

    )

    solve(mid_1+1,r_1,mid_2,r_2)

    solve(mid1​+1,r1​,mid2​,r2​) 。此前暴力回退、加边使之满足前提条件

  5. 递归

    s

    o

    l

    v

    e

    (

    l

    1

    ,

    m

    i

    d

    1

    1

    ,

    l

    2

    ,

    m

    i

    d

    2

    )

    solve(l_1,mid_1-1,l_2,mid_2)

    solve(l1​,mid1​−1,l2​,mid2​)。同理。

递归到边界就不用多说了吧。

时间复杂度

O

(

M

log

2

M

+

Q

)

O(M\log^2M+Q)

O(Mlog2M+Q)。

CODE

#include<set>
#include<queue>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 200005
#define ENDL putchar('\n')
#define LL long long
#define DB double
#define lowbit(x) ((-x) & (x))
LL read() {
LL f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f * x;
}
int n,m,i,j,s,o,k;
int U[MAXN],V[MAXN];
vector<int> g[MAXN];
int fa[MAXN],ds[MAXN],siz[MAXN];
int findd(int x) {if(x == fa[x]) return 0;return findd(fa[x])^ds[x];}
int findf(int x) {return x==fa[x] ? x:findf(fa[x]);}
vector<int> st;
bool unionSet(int a,int b) {
int u = findf(a),v = findf(b);
if(siz[u] > siz[v]) swap(u,v),swap(a,b);
int d1 = findd(a),d2 = findd(b);
if(u == v) {
return d1 ^ d2;
}
if(d1 == d2) ds[u] = 1;
else ds[u] = 0;
siz[v] += siz[u]; fa[u] = v;
st.push_back(u);
return 1;
}
void POP() {
int u = st.back(); st.pop_back();
int v = fa[u];
ds[u] = 0; siz[v] -= siz[u];
fa[u] = u; return ;
}
int maxr[MAXN];
int li[MAXN],ri[MAXN];
void solve(int l,int r,int l2,int r2) {
if(l > r || l2 > r2) return ;
if(l2 == r2) {
for(int i = l;i <= r;i ++) maxr[i] = l2;
return ;
}
int mid = (l + r) >> 1,le = (int)st.size(),rr = max(l2,mid-1);
int flag = 0;
for(int i = l;i <= mid;i ++) if(i) flag |= 1^unionSet(U[i],V[i]);
int le2 = (int)st.size();
if(flag) rr = r2;
for(int i = min(r2,m);i > mid && i >= l2 && i > rr;i --) {
flag |= 1^unionSet(U[i],V[i]);
if(flag) {rr = i;break;}
}
maxr[mid] = rr;
while((int)st.size() > le2) POP();
solve(mid+1,r,rr,r2);
while((int)st.size() > le) POP();
for(int i = min(r2,m);i >= rr;i --) unionSet(U[i],V[i]);
solve(l,mid-1,l2,rr);
while((int)st.size() > le) POP();
return ;
}
int main() {
n = read();m = read();int Q = read();
for(int i = 1;i <= m;i ++) {
s = read();o = read();
g[s].push_back(o);
g[o].push_back(s);
U[i] = s; V[i] = o;
}
int rr = 0;
for(int i = 1;i <= Q;i ++) li[i] = read(),ri[i] = read(),rr = max(li[i],rr);
for(int i = 1;i <= n;i ++) fa[i] = i,ds[i] = 0,siz[i] = 1;
solve(0,m,0,m+1);
for(int i = 1;i <= Q;i ++) {
s = li[i];o = ri[i];
if(maxr[s-1] > o) printf("YES\n");
else printf("NO\n");
}
return 0;
}

[CF1386C] Joker (IOI 赛制,分治,整体二分+可回退并查集)的更多相关文章

  1. CQD(陈丹琦)分治 & 整体二分——专题小结

    整体二分和CDQ分治 有一些问题很多时间都坑在斜率和凸壳上了么--感觉斜率和凸壳各种搞不懂-- 整体二分 整体二分的资料好像不是很多,我在网上找到了一篇不错的资料:       整体二分是个很神的东西 ...

  2. 一篇自己都看不懂的CDQ分治&整体二分学习笔记

    作为一个永不咕咕咕的博主,我来更笔记辣qaq CDQ分治 CDQ分治的思想还是比较简单的.它的基本流程是: \(1.\)将所有修改操作和查询操作按照时间顺序并在一起,形成一段序列.显然,会影响查询操作 ...

  3. Cdq分治整体二分学习记录

    这点东西前前后后拖了好几个星期才学会……还是自己太菜啊. Cdq分治的思想是:把问题序列分割成左右两个,先单独处理左边,再处理左边对右边的影响,再单独处理右边.这样可以消去数据结构上的一个log,降低 ...

  4. [学习笔记] CDQ分治&整体二分

    突然诈尸.png 这两个东西好像都是离线骗分大法... 不过其实这两个东西并不是一样的... 虽然代码长得比较像 CDQ分治 基本思想 其实CDQ分治的基本思想挺简单的... 大概思路就是长这样的: ...

  5. 算法笔记--CDQ分治 && 整体二分

    参考:https://www.luogu.org/blog/Owencodeisking/post-xue-xi-bi-ji-cdq-fen-zhi-hu-zheng-ti-er-fen 前置技能:树 ...

  6. CDQ分治&整体二分学习个人小结

    目录 小结 CDQ分治 二维LIS 第一道裸题 bzoj1176 Mokia bzoj3262 陌上花开 bzoj 1790 矩形藏宝地 hdu5126四维偏序 P3157 [CQOI2011]动态逆 ...

  7. luogu P5473 [NOI2019]I 君的探险 交互 随机 二分 分治 整体二分

    LINK:I 君的探险 神仙题! 考虑一个暴力的做法 每次点亮一个点 询问全部点 这样询问次数为 \(\frac{n\cdot (n-1)}{2}\) 可以通过前5个点. 考虑都为A的部分分 发现一个 ...

  8. Codeforces 938G Shortest Path Queries [分治,线性基,并查集]

    洛谷 Codeforces 分治的题目,或者说分治的思想,是非常灵活多变的. 所以对我这种智商低的选手特别不友好 脑子不好使怎么办?多做题吧-- 前置知识 线性基是你必须会的,不然这题不可做. 推荐再 ...

  9. 线段树分治总结(线段树分治,线段树,并查集,树的dfn序,二分图染色)

    闲话 stO猫锟学长,满脑子神仙DS 网上有不少Dalao把线段树分治也归入CDQ分治? 还是听听YCB巨佬的介绍: 狭义:只计算左边对右边的贡献. 广义:只计算外部对内部的贡献. 看来可以理解为广义 ...

随机推荐

  1. 开发工具-在线生成GUID

    更新记录 2022年6月11日 记录开始. https://www.toolbaba.cn/d/dev_guid http://tool.pfan.cn/guidgen https://www.iam ...

  2. 网心云在PVE下三种磁盘IO模式(No cache,Write through,Write back)选择与优化指南

    ---------------------------------------------------------------------------------------------------- ...

  3. WPF中Popup控件的使用

    一.Popup控件的主要属性 Popup表示具有内容的弹出窗口,其主要属性为: Child:获取或设置 Popup控件的内容. IsOpen:获取或设置一个值,该值指示Popup 是否可见 Place ...

  4. SAP 实例- 下拉框

    效果图 源代码 REPORT rsdemo_dropdown_listbox . DATA init. TABLES scarr. TABLES spfli. TABLES sflight. TABL ...

  5. 编程技巧│提高 Javascript 代码效率的技巧

    目录 一.变量声明 二.三元运算符 三.解构赋值 四.解构交换 五.箭头函数 六.字符串模版 七.多值匹配 八.ES6对象简写 九.字符串转数字 十.次方相乘 十一.数组合并 十二.查找数组最大值最小 ...

  6. 在VMware Workstation 16上安装Windows7虚拟机以及VMware tools安装失败解决方法

    安装VMware Workstation 16 搜素"VMware Workstation下载" 下载 VMware Workstation Pro 下载Windows7系统镜像 ...

  7. Android (微信扫码登录) 获取微信二维码+扫码登录

    话不多说  直接上菜! 一.因为是微信扫码登录,所有要在微信开放平台  微信开放平台 (qq.com) 进行注册----- 如下 1.资源中心 里面也有详细的官方讲解,里面也有demo  可以下载 2 ...

  8. cmd中常用的dos命令

    在电脑中除了我们常见的图形界面之外,图形页面的操作相信都会.那么还有在cmd执行的一些dos命令,可以简单记一下,方便日后复习所用 首先打开cmd窗口,windows+R,然后在对话框输入cmd,进入 ...

  9. 跨平台(32bit和64bit)的 printf 格式符 %lld 输出64位的解决方式

    问题描述 在 C/C++ 开发中,使用 printf 打印 64 位变量比较常用,通常在 32 位系统中使用 %lld 输出 64 位的变量,而在 64 位系统中则使用 %ld: 如果在 32 位系统 ...

  10. 《AlignedReID:Surpassing Human-Level Performance in Person Re-Identification》理解