4025: 二分图

题意:加入边,删除边,查询当前图是否为二分图


本来想练lct,然后发现了线段树分治的做法,感觉好厉害。

lct做法的核心就是维护删除时间的最大生成树


首先口胡一个分块做法,和hnoi2016第一题类似的偏序关系,一样做。


线段树分治

数据结构题中如果使用对时间cdq分治,要求每个操作独立,不能很好的处理撤销(删除)操作。

采取线段树区间标记的思想

对于一个操作,它的存在时间是\([l,r]\)

我们模仿线段树打标记的过程进行分治,\(cdq(l,r,S)\)表示当前处理时间\([l,r]\),操作集合为\(S\)

如果区间就是当前区间,那么进行操作

否则继续递归



对于本题,用启发式合并 不路径压缩的并查集实现加边和撤销

越卡常越慢是smg

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
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, T, u, v, l, r;
struct edge {
int u, v, l, r;
bool operator <(const edge &a) const {return l == a.l ? r < a.r : l < a.l;}
};
typedef vector<edge> meow;
meow a; int top;
namespace ufs {
struct node {int fa, val, size;} t[N];
struct info {int x, y; node a, b;} st[N];
inline void init() {for(int i=1; i<=n; i++) t[i] = (node){i, 0, 1};}
inline int find(int x) {while(t[x].fa != x) x = t[x].fa; return x;}
inline int dis(int x) {
int ans=0;
while(t[x].fa != x) ans ^= t[x].val, x = t[x].fa;
return ans;
}
inline void link(int x, int y) {
int val = dis(x) ^ dis(y) ^ 1;
x = find(x); y = find(y);
st[++top] = (info) {x, y, t[x], t[y]};
if(t[x].size > t[y].size) swap(x, y);
t[x].fa = y; t[x].val = val; t[y].size += t[x].size;
}
inline void recov(int bot) {
while(top != bot) {
info &now = st[top--];
t[now.x] = now.a; t[now.y] = now.b;
}
}
} using namespace ufs; void cdq(int l, int r, meow &a) {
int mid = (l+r)>>1, bot = top;
meow b, c;
for(int i=0; i<(int)a.size(); i++) {
edge &now = a[i];
int x = now.u, y = now.v;
if(now.l == l && now.r == r) {
int p = find(x), q = find(y);
if(p == q) {
int val = dis(x) ^ dis(y);
if(val == 0) {
for(int i=l; i<=r; i++) puts("No");
recov(bot); return;
}
} else link(x, y);
}
else if(now.r <= mid) b.push_back(now);
else if(mid < now.l) c.push_back(now);
else b.push_back( (edge){now.u, now.v, now.l, mid} ), c.push_back( (edge){now.u, now.v, mid+1, now.r} );
}
if(l == r) puts("Yes");
else cdq(l, mid, b), cdq(mid+1, r, c);
recov(bot);
} int main() {
//freopen("in", "r", stdin);
n=read(); m=read(); T=read();
for(int i=1; i<=m; i++) {
u=read(), v=read(), l=read()+1, r=read();
if(l > r) continue;
a.push_back((edge){u, v, l, r});
}
init();
cdq(1, T, a);
}

BZOJ 4025: 二分图 [线段树CDQ分治 并查集]的更多相关文章

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

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

  2. bzoj 4025 二分图——线段树分治+LCT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4025 线段树分治,用 LCT 维护链的长度即可.不过很慢. 正常(更快)的方法应该是线段树分 ...

  3. 【openjudge】C15C Rabbit's Festival CDQ分治+并查集

    题目链接:http://poj.openjudge.cn/practice/C15C/ 题意:n 点 m 边 k 天.每条边在某一天会消失(仅仅那一天消失).问每一天有多少对点可以相互到达. 解法:开 ...

  4. BZOJ 3939 [Usaco2015 Feb]Cow Hopscotch ——线段树 CDQ分治

    显然dp[i][j]=ps[i-1][j-1]-sigma(dp[k<i][l<j],a[i][j]=a[k][l]) 考虑对于每一种颜色都开一颗区间线段树,但是空间不够. 所以我们可以动 ...

  5. COGS 577 蝗灾 线段树+CDQ分治

    第一次写cdq分治 感谢hhd&lty 这20亿对CP的指导(逃) 其实 就是 递归看左半部分对右半部分的贡献 (树状数组写挂了--临时改的线段树[大写的尴尬]) //By SiriusRen ...

  6. hdu_5354_Bipartite Graph(cdq分治+并查集判二分图)

    题目链接:hdu_5354_Bipartite Graph 题意: 给你一个由无向边连接的图,问对于每一个点来说,如果删除这个点,剩下的点能不能构成一个二分图. 题解: 如果每次排除一个点然后去DFS ...

  7. BZOJ 2333 棘手的操作(离线+线段树+带权并查集)

    这题搞了我一天啊...拍不出错原来是因为极限数据就RE了啊,竟然返回WA啊.我的线段树要开8倍才能过啊... 首先可以发现除了那个加边操作,其他的操作有点像线段树啊.如果我们把每次询问的联通块都放在一 ...

  8. BZOJ 2733 线段树的合并 并查集

    思路: 1.线段树合并(nlogn的) 2.splay+启发式合并 线段树合并比较好写 我手懒 //By SiriusRen #include <cstdio> #include < ...

  9. BZOJ 2733 [HNOI2012]永无乡 (权值线段树启发式合并+并查集)

    题意: n<=1e5的图里,在线连边.查询某连通块第k大 思路: 练习线段树合并的好题,因为依然记得上一次启发式合并trie的时候内存爆炸的恐怖,所以这次还是用了动态开点.回收 听说启发式合并s ...

随机推荐

  1. 数学3(博弈+splya)

    数学3(博弈+splya) 标签: 数学 hdu_5194 (打表找规律) 题意 有n和黑球和m个白球,现在一个个的取出这些球,如果是黑球则当前标记为1,白球为0,那么当取完这些球会得到一些序列.问你 ...

  2. Ajax 案例之三级联动

    每次在博客园网站写博客,格式真的好难搞,还望好心人告知更好的编辑工具.接下来进入正题:三级联动(其效果演示可看我的博文Ajax 学习总结 末尾). 数据表设计(Oracle) 新建数据表 Employ ...

  3. 修改mysql密码的四种方法

    方法1: 用SET PASSWORD命令 首先登录MySQL. 格式:mysql> set password for 用户名@localhost = password('新密码'); 例子:my ...

  4. 对于hive使用的一点记录

    最近一段时间因工作需要接触了一些hive上的使用!当然大部分都是比较基本的使用,仅当入门!各位看到有不足之处望多多指正! 废话不多说,开始: 首先是创建数据库 create database '数据库 ...

  5. tinyxml的封装与使用(转载)

    tinyxml是个高效精简的xml解析开源代码. 针对tinyxml直接使用对于对xml不是很熟悉的入门新手来说,有些概念难以理解,因此我将其封装后,供大家使用. 头文件: #include &quo ...

  6. 安装Ruby、Sass与Compass

    sass基于Ruby语言开发而成,因此安装sass前需要安装Ruby.(注:mac下自带Ruby无需在安装Ruby!) window下安装SASS首先需要安装Ruby,先从官网下载Ruby并安装.安装 ...

  7. final、finally、finalize

    final是一个修饰词.可以修饰变量.方法.类 final修饰变量时分为两种 )1.修饰成员变量:该成员变量不可以被二次赋值.也就是说成员变量无法改变.且该成员变量要么在定义时初始化,要么在构造器中进 ...

  8. thinkphp5自动完成

  9. hql(Hibernate Query Language)

    1.Criteria查询对查询条件进行了面向对象封装,符合编程人员的思维方式,不过HQL(Hibernate Query Language)查询提供了更加丰富的和灵活的查询特性,因此Hibernate ...

  10. MySQL 取得小时分钟部分

    MySQL 取得小时分钟部分 SELECT `CpParkID` , DATE_FORMAT( `UPDATE_TIME` , '%H:%i' )FROM `cp_park`WHERE HOUR( ` ...