Description

神犇有一个n个节点的图。因为神犇是神犇,所以在T时间内一些边会出现后消失。神犇要求出每一时间段内这个图是否是二分图。这么简单的问题神犇当然会做了,于是他想考考你。

Input

输入数据的第一行是三个整数n,m,T。

第2行到第m+1行,每行4个整数u,v,start,end。第i+1行的四个整数表示第i条边连接u,v两个点,这条边在start时刻出现,在第end时刻消失。

Output

输出包含T行。在第i行中,如果第i时间段内这个图是二分图,那么输出“Yes”,否则输出“No”,不含引号。

Sample Input

3 3 3
1 2 0 2
2 3 0 3
1 3 1 2

Sample Output

Yes
No
Yes

HINT

样例说明:

0时刻,出现两条边1-2和2-3。

第1时间段内,这个图是二分图,输出Yes。

1时刻,出现一条边1-3。

第2时间段内,这个图不是二分图,输出No。

2时刻,1-2和1-3两条边消失。

第3时间段内,只有一条边2-3,这个图是二分图,输出Yes。

数据范围:

n<=100000,m<=200000,T<=100000,1<=u,v<=n,0<=start<=end<=T。

Solution

首先看怎么静态判能不能二分,一条一条边加进去,如果这条边加上会变成一个环,并且这个环还是奇环,那就不能二分;反之,可以

然后看动态的,动态的麻烦就在删除,因为可能把一条树边删掉之后,会有一条非树边代替它变成一条树边,这个做不了;所以就弄一个LCT维护这个树,维护这个图以删除时间为关键字的最大生成树,这样就不会有上述情况发生了

然后按照套路,离线解决

(PS:从早上开始调,一直调到晚上,开始的时候造数据的程序还写错了,会使标程RE,然后有一次其实改对了,但因为数据造错,一直拍不上,结果就和gt拿了一个正确的程序调了半个小时)

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=100000+10,MAXM=200000+10,inf=0x3f3f3f3f;
int n,m,tT,V[MAXN+MAXM],sum,f[MAXN+MAXM];
struct edge{
int u,v;
};
edge side[MAXM];
struct data{
int opt,val,t,id;
inline bool operator < (const data &A) const {
return t<A.t||t==A.t&&opt>A.opt;
};
};
data p[MAXM<<1];
#define lc(x) ch[(x)][0]
#define rc(x) ch[(x)][1]
struct LCT{
int ch[MAXN+MAXM][2],fa[MAXN+MAXM],rev[MAXN+MAXM],Mn[MAXN+MAXM],id[MAXN+MAXM],stack[MAXN+MAXM],cnt,val[MAXN+MAXM],size[MAXN+MAXM];
inline void init()
{
memset(Mn,inf,sizeof(Mn));
memset(val,inf,sizeof(val));
}
inline bool nroot(int x)
{
return lc(fa[x])==x||rc(fa[x])==x;
}
inline void reverse(int x)
{
std::swap(lc(x),rc(x));
rev[x]^=1;
}
inline void pushup(int x)
{
size[x]=size[lc(x)]+size[rc(x)]+1;
Mn[x]=val[x],id[x]=x;
if(Mn[lc(x)]<Mn[x])Mn[x]=Mn[lc(x)],id[x]=id[lc(x)];
if(Mn[rc(x)]<Mn[x])Mn[x]=Mn[rc(x)],id[x]=id[rc(x)];
}
inline void pushdown(int x)
{
if(rev[x])
{
if(lc(x))reverse(lc(x));
if(rc(x))reverse(rc(x));
rev[x]=0;
}
}
inline void rotate(int x)
{
int f=fa[x],p=fa[f],c=(rc(f)==x);
if(nroot(f))ch[p][rc(p)==f]=x;
fa[ch[f][c]=ch[x][c^1]]=f;
fa[ch[x][c^1]=f]=x;
fa[x]=p;
pushup(f);
pushup(x);
}
inline void splay(int x)
{
cnt=0;
stack[++cnt]=x;
for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
while(cnt)pushdown(stack[cnt--]);
for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
pushup(x);
}
inline void access(int x)
{
for(register int y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x);
}
inline int findroot(int x)
{
access(x);splay(x);
while(lc(x))pushdown(x),x=lc(x);
splay(x);
return x;
}
inline void makeroot(int x)
{
access(x);splay(x);reverse(x);
}
inline void split(int x,int y)
{
makeroot(x);access(y);splay(y);
}
inline void link(int x,int y)
{
makeroot(x);fa[x]=y;
}
inline void cut(int x,int y)
{
split(x,y);fa[x]=lc(y)=0;pushup(y);
}
};
LCT T;
#undef lc
#undef rc
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void add(int now)
{
int u=side[p[now].id].u,v=side[p[now].id].v,sn=p[now].id+n;
if(u==v)
{
f[sn-n]=1;sum++;
return ;
}
if(T.findroot(u)!=T.findroot(v))T.val[sn]=p[now].val,T.link(sn,u),T.link(sn,v),V[sn-n]=1;
else
{
T.split(u,v);
int so=T.id[v],nt=T.size[v]>>1;
if(p[now].val>T.Mn[v])
{
if(!(nt&1))sum++,f[so-n]=1;
T.cut(so,side[so-n].u);
T.cut(so,side[so-n].v);
T.val[sn]=p[now].val;
T.link(sn,u);
T.link(sn,v);
V[so-n]=0;V[sn-n]=1;
}
else if(!(nt&1))sum++,f[sn-n]=1;
}
}
inline void del(int now)
{
int sn=p[now].id+n;
sum-=f[sn-n];
if(V[sn-n])
{
V[sn-n]=f[sn-n]=0;
T.cut(sn,side[sn-n].u);T.cut(sn,side[sn-n].v);
}
else f[sn-n]=0;
}
int main()
{
read(n);read(m);read(tT);
for(register int i=1;i<=m;++i)
{
int u,v,st,ed;
read(u);read(v);read(st);read(ed);
side[i].u=u;side[i].v=v;
p[i].t=st;p[i].val=ed;p[i].id=i;p[i].opt=1;
p[i+m].t=ed;p[i+m].id=i;p[i+m].opt=0;
}
std::sort(p+1,p+m*2+1);
T.init();
for(register int i=1,j=1;i<=tT;++i)
{
for(;p[j].t<i&&j<=m*2;++j)
if(p[j].opt)add(j);
else del(j);
if(sum)puts("No");
else puts("Yes");
}
return 0;
}

【刷题】BZOJ 4025 二分图的更多相关文章

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

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

  2. bzoj 4025 二分图 分治+并查集/LCT

    bzoj 4025 二分图 [题目大意] 有n个点m条边,边会在start时刻出现在end时刻消失,求对于每一段时间,该图是不是一个二分图. 判断二分图的一个简单的方法:是否存在奇环 若存在奇环,就不 ...

  3. BZOJ 4025: 二分图 [线段树CDQ分治 并查集]

    4025: 二分图 题意:加入边,删除边,查询当前图是否为二分图 本来想练lct,然后发现了线段树分治的做法,感觉好厉害. lct做法的核心就是维护删除时间的最大生成树 首先口胡一个分块做法,和hno ...

  4. bzoj 4025: 二分图

    Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简单的问题神犇当然会做了,于是他想考考你. 解题报告: ...

  5. BZOJ 4025 二分图(时间树+并查集)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4025 [题目大意] 给出一张图,有些边只存在一段时间,问在一个每个时间段, 这张图是否 ...

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

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

  7. 「bzoj 4025: 二分图」

    题目 显然二分图没有奇环 于是考虑使用并查集维护一下看看是否存在奇环 我们可以考虑加权并查集,维护出\(x\)到\(fa_x\)的实际距离 由于我们只需要考虑奇偶性,于是我们处理出到根的路径异或一下就 ...

  8. bzoj 4025 二分图 lct

    题目传送门 题解: 首先关于二分图的性质, 就是没有奇环边. 题目其实就是让你判断每个时段之内有没有奇环. 其次 lct 只能维护树,(反正对于我这种菜鸟选手只会维护树), 那么对于一棵树来说, 填上 ...

  9. BZOJ 4025 二分图 LCT维护最大生成树

    怎么说呢,我也不知道该咋讲,你就手画一下然后 yy 一下就发现这么做是对的. 为什么我明明都想出来了,却还是讲不出来啊~ #include <cstdio> #include <ve ...

随机推荐

  1. Python:静态方法、类方法、实例方法

    1. 静态方法@staticmethod (1)无需自身对象的self参数和自身类的cls参数,可直接通过 类名.方法名 进行调用 (2)Python中并不是真正意义上的静态方法,因为类定义本身就是个 ...

  2. 【搜索好题】bzoj1501 [NOI2005]智慧珠游戏

    bzoj1501 [NOI2005]智慧珠游戏 搜索苟逼题系列. 暴力枚举每一种情况(包括旋转翻转全都考虑在内)然后码出代码. (正解似乎不是这样子的) 那年好像还有平衡树苟逼题维护数列233333心 ...

  3. Android开发笔记——ListView模块、缓存及性能

    ListView是Android开发中最常用的组件之一.本文将重点说明如何正确使用ListView,以及使用过程中可能遇到的问题. ListView开发模块 图片缓存 可能遇到的问题 一.ListVi ...

  4. DataTable保存与读取 stream

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...

  5. arduino蜂鸣器的使用

    一:蜂鸣器的使用 控制要求:模拟救护车响声 实物连接图: 电路原理图: 控制代码: //智慧自动化2018.6.11 ;//设置控制蜂鸣器的数字IO脚 void setup() { pinMode(b ...

  6. ddms+adt+jdk的安装及调试开发安卓

    _______ ddms+adt+jdk的安装及调试开发安卓 目录 阐述 1 1  jdk安装 1 2  sdk安装 3 3  Eclipse安装 6 4  ADT安装 10 5  Ddms使用 16 ...

  7. 转发——谷歌云官方:一小时掌握深度学习和 TensorFlow

    转发——谷歌云官方:一小时掌握深度学习和 TensorFlow 本文转发自新智元,链接如下: http://mp.weixin.qq.com/s?__biz=MzI3MTA0MTk1MA==& ...

  8. [SHELL]查看端口,文件,服务关系的四个命令netstat,lsof,fuser,nmap

    一,netstat (1)简介 netstat主要是用来打印系统网络的状态信息,当输入netstat后,输出如下: 可以看出,netstat的输出分为两个部分组成: 一个是Active Interne ...

  9. CsvHelper文档-4映射

    CsvHelper文档-4映射 类映射 有时候你的类成员和csv的header不一定对应,有时候你的csv文件根本就没有header行,你需要特别制定一个成员的index,你不能依靠.net中默认的顺 ...

  10. ES数据备份到HDFS

    1.准备好HDFS(这里我是本机测试) 2.es 安装repository-hdfs插件 (如es为多节点需在每个节点都安装插件) elasticsearch-plugin install repos ...