题面

给一个

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;
}

最新文章

  1. ORA-00494: enqueue [CF] held for too long (more than 900 seconds) by 'inst 1, osid 5166'
  2. 大型网站提速关键技术(页面静态化,memcached,MySql优化)(三)
  3. Ext.Net 学习随笔 003 Panel基本使用
  4. TW2015技术雷达中文版发布
  5. Windows 下用 gogs 配置局域网 git server
  6. lib3ds类库
  7. 请问用Inno_Setup打包文件夹时怎么排除其中一个文件?
  8. SQL日志文件的作用
  9. 学习了几天的jQuery Mobile的一点感受
  10. 切割 bitmap
  11. Unity 制作虚拟手柄例子
  12. differ比较两个字符串的差异
  13. Cocos2d-x 3.1.1开发环境
  14. js中的整型都是用double存储的,有时候不精确,如,
  15. P4语言编程快速开始 实践一
  16. jquery通过ajax向后台发送(checkbox)数组,并在后台接收,(发送的数据是checkedbox)
  17. 阿里云Prismplayer-Web播放器的使用
  18. sass 安装与使用
  19. python使用
  20. JavaScript变量声明var,let.const

热门文章

  1. @vue/cli3+配置build命令构建测试包&amp;正式包
  2. FFT 小记
  3. ExtJS 布局-Accordion布局(Accordion layout)
  4. Centos 创建新的虚拟环境
  5. sql-关键词的大小写与注释
  6. 【摸鱼神器】UI库秒变低代码工具——表单篇(一)设计
  7. 零基础学Java(7)大数
  8. 5-8 Resource 静态资源服务器
  9. day09 集合排序_Collection接口与Collections工具类
  10. Eslint 项目笔记