BZOJ4025 二分图(线段树分治+并查集)
之前学了一下线段树分治,这还是第一次写。思想其实挺好理解,即离线后把一个操作影响到的时间段拆成线段树上的区间,并标记永久化。之后一块处理,对于某个节点表示的时间段,影响到他的就是该节点一直到线段树根的所有操作。(语死早)这样可以把操作的插入和删除改为只有插入。
具体到这题,由于并查集没法删除边,我们考虑线段树分治。之后要考虑的问题就是如何用并查集判断是否为二分图,也即是否含奇环。假设现在图中有一个偶环,若给偶环两点加了一条边,可以发现无论去掉原偶环上哪一条边都不会改变新出现环的奇偶性。于是我们只要用并查集维护出每个点到根的距离(按秩合并),从而维护出任意两点距离的奇偶性,若加入一条环边则判断是否会构成奇环,有奇环直接退出,没有则扔掉这条边不管。每次处理完线段树一个节点后要把操作还原,以避免影响其他无关节点。这个可以在操作时用栈记录,退出时还原。
这个题就做完了。然而代码能力极差的我发现自己连并查集都差点不会写了。以及,图中会有自环,有自环就不是二分图,我开始竟然反方向判掉了……还有会有出现时刻与消失时刻相同的边,RE了好几发。总之调到吐血,早日退役保平安。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 100010
int n,m,T,L[N<<],R[N<<],fa[N],deep[N],dis[N],v[N];
struct edge{int x,y;};
struct data{int x,fa,deep,v;};
vector<edge> tree[N<<];
stack<data> undo[N<<];
bool ans[N];
void build(int k,int l,int r)
{
L[k]=l,R[k]=r;
if (l==r) return;
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
}
void add(int k,int l,int r,edge e)
{
if (L[k]==l&&R[k]==r) {tree[k].push_back(e);return;}
int mid=L[k]+R[k]>>;
if (r<=mid) add(k<<,l,r,e);
else if (l>mid) add(k<<|,l,r,e);
else add(k<<,l,mid,e),add(k<<|,mid+,r,e);
}
int find(int x)
{
if (fa[x]==x) return x;
int p=find(fa[x]);
dis[x]=dis[fa[x]]^v[x];
return p;
}
void merge(int k,int x,int y,int p)
{
if (deep[x]<deep[y]) swap(x,y);
data a;
a.x=y;a.fa=x;a.deep=deep[x];a.v=v[y];
undo[k].push(a);
fa[y]=x;v[y]=p;dis[y]=dis[x]^p;
if (deep[y]==deep[x]) deep[x]++;
}
void solve(int k)
{
int s=tree[k].size();
bool flag=;
for (int i=;i<s;i++)
{
if (tree[k][i].x==tree[k][i].y) {flag=;break;}
int p=find(tree[k][i].x),q=find(tree[k][i].y);
if (p!=q) merge(k,p,q,dis[tree[k][i].x]^dis[tree[k][i].y]^);
else if (dis[tree[k][i].x]^dis[tree[k][i].y]^) {flag=;break;}
}
if (L[k]<R[k]&&!flag) solve(k<<),solve(k<<|);
else if (flag) for (int i=L[k];i<=R[k];i++) ans[i]=;
while (!undo[k].empty())
{
data a=undo[k].top();
fa[a.x]=a.x;
deep[a.fa]=a.deep;
dis[a.x]=v[a.x]=a.v;
undo[k].pop();
}
}
int main()
{
freopen("bzoj4025.in","r",stdin);
freopen("bzoj4025.out","w",stdout);
n=read(),m=read(),T=read();
build(,,T);
for (int i=;i<=m;i++)
{
edge e;e.x=read(),e.y=read();
int s=read()+,t=read();
if (s<=t) add(,s,t,e);
}
for (int i=;i<=n;i++) fa[i]=i,deep[i]=v[i]=dis[i]=;
solve();
for (int i=;i<=T;i++)
if (ans[i]) printf("No\n");
else printf("Yes\n");
fclose(stdin);fclose(stdout);
return ;
}
BZOJ4025 二分图(线段树分治+并查集)的更多相关文章
- bzoj4025二分图(线段树分治 并查集)
/* 思维难度几乎没有, 就是线段树分治check二分图 判断是否为二分图可以通过维护lct看看是否链接出奇环 然后发现不用lct, 并查集维护奇偶性即可 但是复杂度明明一样哈 */ #include ...
- [BZOJ4025]二分图(线段树分治,并查集)
4025: 二分图 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2191 Solved: 800[Submit][Status][Discuss] ...
- 2018.09.30 bzoj4025: 二分图(线段树分治+并查集)
传送门 线段树分治好题. 这道题实际上有很多不同的做法: cdq分治. lct. - 而我学习了dzyo的线段树分治+并查集写法. 所谓线段树分治就是先把操作分成lognlognlogn个连续不相交的 ...
- BZOJ3237:[AHOI2013]连通图(线段树分治,并查集)
Description Input Output Sample Input 4 5 1 2 2 3 3 4 4 1 2 4 3 1 5 2 2 3 2 1 2 Sample Output Connec ...
- Bzoj1018/洛谷P4246 [SHOI2008]堵塞的交通(线段树分治+并查集)
题面 Bzoj 洛谷 题解 考虑用并查集维护图的连通性,接着用线段树分治对每个修改进行分治. 具体来说,就是用一个时间轴表示图的状态,用线段树维护,对于一条边,我们判断如果他的存在时间正好在这个区间内 ...
- BZOJ 1018: [SHOI2008]堵塞的交通traffic(线段树分治+并查集)
传送门 解题思路 可以离线,然后确定每个边的出现时间,算这个排序即可.然后就可以线段树分治了,连通性用并查集维护,因为要撤销,所以要按秩合并,时间复杂度\(O(nlog^2 n)\) 代码 #incl ...
- BZOJ3237 AHOI2013连通图(线段树分治+并查集)
把查询看做是在一条时间轴上.那么每条边都有几段存在时间.于是线段树分治就好了. 然而在bzoj上t掉了,不知道是常数大了还是写挂了. 以及brk不知道是啥做数组名过不了编译. #include< ...
- BZOJ4025 二分图 线段树分治、带权并查集
传送门 如果边不会消失,那么显然可以带权并查集做(然后发现自己不会写带权并查集) 但是每条边有消失时间.这样每一条边产生贡献的时间对应一段区间,故对时间轴建立线段树,将每一条边扔到线段树对应的点上. ...
- bzoj4025-二分图【线段树分治,并查集】
正题 题目链接:https://darkbzoj.tk/problem/4025 题目大意 \(n\)个点\(m\)条边,每条边会在一个\(T\)以内的时间段内出现,对于任意一个\(T\)以内的时刻求 ...
随机推荐
- Android学习之基础知识九 — 数据存储(持久化技术)之SQLite数据库存储
前面一讲介绍了数据持久化技术的前两种:文件存储.SharedPreferences存储.下面介绍第三种技术:SQLite数据库存储 一.SQLite数据库存储 SQLite数据库是一款轻量级的关系型数 ...
- docker知识复习
1.镜像基于内容寻址 基于内容寻址的实现,使用了两个目录:/var/lib/docker/image和/var/lib/docker/overlay, 后面的这个根据存储驱动的名称不同,而目录名不同. ...
- iRedMail退信问题的解决(转)
安装完iRedMail之后发现可以给外网发邮件但是收不到外网发来的邮件,查看log发现这么一句话:postfix/postscreen[11355]: NOQUEUE: reject: RCPT fr ...
- (转)vim中多行注释
1.多行注释: 1. 首先按esc进入命令行模式下,按下Ctrl + v,进入列(也叫区块)模式; 2. 在行首使用上下键选择需要注释的多行; 3. 按下键盘(大写)“I”键,进入插入模式: ...
- ORA-14551: 无法在查询中执行 DML 操作
编写了一个oracle函数,函数体内实现一系列数据库的逻辑处理,涉及到数据的增删等操作,返回NCLOB类型. 然后通过查询方式调用函数: SELECT PKG.MY_FUN('A') FROM DUA ...
- React-redux-saga
新建sagas.js import { takeEvery , put} from 'redux-saga/effects' import axios from 'axios'; import { G ...
- 清除EasyUi combotree下拉树的值
由于测试自带的$(“node”).combotree("clear');问题始终解决不了 最终方法: Hdata是JSON数据源, 在它动态加在成功之后(节点全部显示出来,并且可以选择)再清 ...
- GBDT和随机森林的区别
GBDT和随机森林的相同点: 1.都是由多棵树组成 2.最终的结果都是由多棵树一起决定 GBDT和随机森林的不同点: 1.组成随机森林的树可以是分类树,也可以是回归树:而GBDT只由回归树组成 2.组 ...
- Intel x86_64 Architecture Background 3
多层次的cache结构解决了CPU和DRAM之间处理速度不一致的问题,在Intel体系架构下,CPU核心和主存DRAM之间有着三层的cache.其中一层缓存L1和二层缓存L2在CPU核心(core)中 ...
- ABP+AdminLTE+Bootstrap Table权限管理系统第三节--abp分层体系,实体相关及ABP模块系统
返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 ABP模块系统 说了这么久,还没有详细说到abp框架,abp其实基于DDD(领域驱动设计)原则的细看分层如下: 再 ...