P5787 二分图 /【模板】线段树分治
题目描述
神犇有一个 nn 个节点的图。
因为神犇是神犇,所以在 kk 时间内有 mm 条边会出现后消失。
神犇要求出每一时间段内这个图是否是二分图。
这么简单的问题神犇当然会做了,于是他想考考你。
原 BZOJ4025。
输入格式
第一行三个整数 n,m,kn,m,k。
接下来 mm 行,每行四个整数 x,y,l,rx,y,l,r,表示有一条连接 x,yx,y 的边在 ll 时刻出现 rr 时刻消失。
输出格式
kk 行,第 ii 行一个字符串 Yes
或 No
,表示在第 ii 时间段内这个图是否是二分图。
输入输出样例
输入 #1
3 3 3 1 2 0 2 2 3 0 3 1 3 1 2
输出 #1
Yes No Yes
说明/提示
样例说明
00 时刻,出现两条边 (1,2)(1,2) 和 (2,3)(2,3)。
第 11 时间段内,这个图是二分图,输出 Yes
。
11 时刻,出现一条边 (1,3)(1,3)。
第 22 时间段内,这个图不是二分图,输出 No
。
22 时刻,(1,2)(1,2) 和 (1,3)(1,3) 两条边消失。
第 33 时间段内,只有一条边 (2,3)(2,3),这个图是二分图,输出 Yes
。
数据范围
n,k = 10^5n,k=105,m = 2\times 10^5m=2×105。1 \le x,y \le n1≤x,y≤n,0 \le l \le r \le k0≤l≤r≤k。
注意
本题设有 hack 数据(Subtask 22),计 00 分,但若没有通过 hack 数据则不算通过本题。
题解
线段树分治康复,代码有注释
代码
1 //每个操作都有一段存在的时间,将所有操作拆分并覆盖到线段树上。 2 //DFS线段树,进入节点的时候加入所有这些节点的操作,出节点的时候撤销这些操作,DFS到叶子的时候统计一下答案。 3 #include<bits/stdc++.h> 4 #define N (100009) 5 using namespace std; 6 int n,m,k,fa[N<<1],dep[N<<1],top; 7 vector<pair<int,int> > e[N<<2]; 8 pair<int,int>st[N<<1]; 9 void Update(int now,int l,int r,int l1,int r1,int x,int y) { 10 if (l>r1 || r<l1) return; 11 if (l1<=l && r<=r1) { 12 e[now].push_back(make_pair(x,y)); 13 return; 14 } 15 int mid=(l+r)>>1; 16 Update(now<<1,l,mid,l1,r1,x,y); 17 Update(now<<1|1,mid+1,r,l1,r1,x,y); 18 } 19 int Find(int x) { 20 return x==fa[x]?x:Find(fa[x]); 21 } 22 void Merge(int fx,int fy) { 23 if (dep[fx]>dep[fy]) swap(fx,fy); 24 fa[fx]=fy; dep[fy]+=(dep[fx]==dep[fy]); 25 st[++top]=make_pair(fx,fy); 26 }//按秩合并并查集,用栈存历史操作,方便撤销 27 void DFS(int now,int l,int r,int flag) { 28 int mid=(l+r)>>1, tmp=top; 29 for (int i=0; i<e[now].size(); ++i) { 30 int x=e[now][i].first, y=e[now][i].second; 31 int fx=Find(x), fy=Find(y), fx_=Find(x+n), fy_=Find(y+n); 32 if (fx==fy) { 33 flag=0; 34 break; 35 } 36 Merge(fx,fy_); Merge(fy,fx_); 37 } 38 if (l<r) DFS(now<<1,l,mid,flag), DFS(now<<1|1,mid+1,r,flag); 39 else puts(flag?"Yes":"No"); 40 for (int i=top; i>tmp; --i) { 41 int fx=st[i].first, fy=st[i].second; 42 fa[fx]=fx; dep[fy]-=(dep[fx]+1==dep[fy]); 43 } 44 top=tmp; 45 }//并查集判断二分图,加入边(x,y)时若x和y在一个集合就不能构成二分图,否则能构成且合并(x,y'),(x',y) 46 int main() { 47 cin>>n>>m>>k; 48 for (int i=1; i<=2*n; ++i) fa[i]=i, dep[i]=1; 49 for (int i=1; i<=m; ++i) { 50 int x,y,l,r; 51 cin>>x>>y>>l>>r; 52 Update(1,0,k-1,l,r-1,x,y); 53 } 54 DFS(1,0,k-1,1); 55 }