BZOJ 4025 二分图 LCT维护最大生成树
怎么说呢,我也不知道该咋讲,你就手画一下然后 yy 一下就发现这么做是对的.
为什么我明明都想出来了,却还是讲不出来啊~
#include <cstdio>
#include <vector>
#include <algorithm>
#define N 800004
#define inf 1000000000
#define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout)
using namespace std;
int n,m,T,cnt;
struct Edge
{
int u,v,s,t;
Edge(int u=0,int v=0,int s=0,int t=0):u(u),v(v),s(s),t(t){}
}e[N];
struct Link_Cut_Tree
{
#define lson p[x].ch[0]
#define rson p[x].ch[1]
int sta[N];
struct Node
{
int min,id,val,size,rev,f,ch[2];
}p[N];
int get(int x)
{
return p[p[x].f].ch[1]==x;
}
int isrt(int x)
{
return !(p[p[x].f].ch[0]==x||p[p[x].f].ch[1]==x);
}
void pushup(int x)
{
p[x].size=(x>n);
p[x].min=p[x].val;
p[x].id=x;
if(lson)
{
p[x].size+=p[lson].size;
if(p[lson].min<p[x].min) p[x].min=p[lson].min,p[x].id=p[lson].id;
}
if(rson)
{
p[x].size+=p[rson].size;
if(p[rson].min<p[x].min) p[x].min=p[rson].min,p[x].id=p[rson].id;
}
}
void mark(int x)
{
if(x) p[x].rev^=1,swap(lson,rson);
}
void pushdown(int x)
{
if(x&&p[x].rev)
{
p[x].rev=0;
if(lson) mark(lson);
if(rson) mark(rson);
}
}
void rotate(int x)
{
int old=p[x].f,fold=p[old].f,which=get(x);
if(!isrt(old)) p[fold].ch[p[fold].ch[1]==old]=x;
p[old].ch[which]=p[x].ch[which^1],p[p[old].ch[which]].f=old;
p[x].ch[which^1]=old,p[old].f=x,p[x].f=fold;
pushup(old),pushup(x);
}
void splay(int x)
{
int u=x,v=0,fa;
for(sta[++v]=u;!isrt(u);u=p[u].f) sta[++v]=p[u].f;
for(;v;--v) pushdown(sta[v]);
for(u=p[u].f;(fa=p[x].f)!=u;rotate(x))
if(p[fa].f!=u)
rotate(get(fa)==get(x)?fa:x);
}
int findroot(int x)
{
Access(x),splay(x);
for(;lson;) x=lson;
return x;
}
void Access(int x)
{
for(int y=0;x;y=x,x=p[x].f)
splay(x),rson=y,pushup(x);
}
void makeroot(int x)
{
Access(x),splay(x),mark(x);
}
void split(int x,int y)
{
makeroot(x),Access(y),splay(y);
}
void link(int x,int y)
{
makeroot(x),p[x].f=y;
}
void cut(int x,int y)
{
makeroot(x),Access(y),splay(y);
p[y].ch[0]=p[x].f=0;
pushup(y);
}
#undef lson
#undef rson
}lct;
int vised[N],sum[N];
vector<int>Add[N],Del[N];
void add_edge(int id)
{
int u=e[id].u;
int v=e[id].v;
int now=id+n;
if(u==v)
{
++sum[e[id].s];
--sum[e[id].t];
}
else
{
if(lct.findroot(u)==lct.findroot(v))
{
lct.split(u,v);
int cur=lct.p[v].id;
if(lct.p[v].size%2==0)
{
++sum[e[id].s];
--sum[min(e[cur-n].t, e[id].t) ];
}
if(lct.p[cur].val<e[id].t)
{
lct.cut(cur, e[cur-n].u);
lct.cut(cur, e[cur-n].v);
lct.p[now].val=e[id].t;
lct.pushup(now);
lct.link(u,now);
lct.link(now,v);
vised[cur-n]=1;
}
}
else
{
lct.p[now].val=e[id].t;
lct.pushup(now);
lct.link(u,now);
lct.link(v,now);
}
}
}
void delete_edge(int id)
{
if(vised[id] || e[id].u==e[id].v) return;
int u=e[id].u;
int v=e[id].v;
lct.cut(id+n,u);
lct.cut(id+n,v);
}
int main()
{
int i,j;
// setIO("input");
scanf("%d%d%d",&n,&m,&T);
for(i=1;i<=n;++i) lct.p[i].val=inf, lct.pushup(i);
for(i=1;i<=m;++i)
{
int u,v,s,t;
scanf("%d%d%d%d",&u,&v,&s,&t);
e[i]=Edge(u,v,s,t);
if(s<t)
{
Add[s].push_back(i);
Del[t].push_back(i);
}
}
for(i=0;i<T;++i)
{
for(j=0;j<(int)Del[i].size();++j)
{
delete_edge(Del[i][j]);
}
for(j=0;j<(int)Add[i].size();++j)
{
add_edge(Add[i][j]);
}
if(i>0) sum[i]+=sum[i-1];
if(sum[i]>0) printf("No\n");
else printf("Yes\n");
}
return 0;
}
BZOJ 4025 二分图 LCT维护最大生成树的更多相关文章
- bzoj 4025 二分图 lct
题目传送门 题解: 首先关于二分图的性质, 就是没有奇环边. 题目其实就是让你判断每个时段之内有没有奇环. 其次 lct 只能维护树,(反正对于我这种菜鸟选手只会维护树), 那么对于一棵树来说, 填上 ...
- bzoj 4025 二分图 分治+并查集/LCT
bzoj 4025 二分图 [题目大意] 有n个点m条边,边会在start时刻出现在end时刻消失,求对于每一段时间,该图是不是一个二分图. 判断二分图的一个简单的方法:是否存在奇环 若存在奇环,就不 ...
- [BZOJ 4025]二分图(线段树分治+带边权并查集)
[BZOJ 4025]二分图(线段树分治+带边权并查集) 题面 给出一个n个点m条边的图,每条边会在时间s到t出现,问每个时间的图是否为一个二分图 \(n,m,\max(t_i) \leq 10^5\ ...
- bzoj 4025 二分图——线段树分治+LCT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4025 线段树分治,用 LCT 维护链的长度即可.不过很慢. 正常(更快)的方法应该是线段树分 ...
- bzoj 4736: 温暖会指引我们前行 (LCT 维护最大生成树)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4736 题面: 寒冬又一次肆虐了北国大地 无情的北风穿透了人们御寒的衣物 可怜虫们在冬夜中发出 ...
- BZOJ 4025: 二分图 [线段树CDQ分治 并查集]
4025: 二分图 题意:加入边,删除边,查询当前图是否为二分图 本来想练lct,然后发现了线段树分治的做法,感觉好厉害. lct做法的核心就是维护删除时间的最大生成树 首先口胡一个分块做法,和hno ...
- 【刷题】BZOJ 4025 二分图
Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简单的问题神犇当然会做了,于是他想考考你. Input ...
- LOJ #121. 「离线可过」动态图连通性 LCT维护最大生成树
这个还是比较好理解的. 你考虑如果所有边构成一棵树的话直接用 LCT 模拟一波操作就行. 但是可能会出现环,于是我们就将插入/删除操作按照时间排序,然后依次进行. 那么,我们就要对我们维护的生成树改变 ...
- BZOJ3514 Codechef MARCH14 GERALD07加强版 LCT维护最大生成树 主席树
题面 考虑没有询问,直接给你一个图问联通块怎么做. 并查集是吧. 现在想要动态地做,那么应该要用LCT. 考虑新加进来一条边,想要让它能够减少一个联通块的条件就是现在边的两个端点还没有联通. 如果联通 ...
随机推荐
- 将dubbo中使用的动态代理作为工具类
ReflectUtils package per.qiao.util.javassistUtil; import java.lang.reflect.Constructor; import java. ...
- java异常那些事
异常的基本定义: 异常情形是指阻止当前方法或者作用域继续执行的问题.在这里一定要明确一点:异常代码某种程度的错误,尽管Java有异常处理机制,但是我们不能以“正常”的眼光来看待异常,异常处理机制的原因 ...
- CentOS7离线安装Mysql(详细安装过程)
Mysql安装 下载mysql离线安装包 https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.27-1.el7.x86_64.rpm-bundle ...
- C#的@标志的使用情况—本篇blog采用Markdown编写
@(C# 参考--出自官方文档入口) 1.使 C# 关键字用作标识符. @ 字符可作为代码元素的前缀,编译器将把此代码元素解释为标识符而非 C# 关键字. 下面的示例使用 @ 字符定义其在 for 循 ...
- [书籍翻译] 《JavaScript并发编程》第七章 抽取并发逻辑
本文是我翻译<JavaScript Concurrency>书籍的第七章 抽取并发逻辑,该书主要以Promises.Generator.Web workers等技术来讲解JavaScrip ...
- JavaScript流程图(精简版)
网址:https://www.processon.com/view/link/5db4f595e4b0c5553741c271 如果链接失效,请及时反馈(在评论区评论),博主会及时更新
- 最近发现了一篇讲解Vue的虚拟DOM,diff很棒的文章,特定记录转载一下
本文章是转载的,为了方便以后复习,特地记录一下.他人请去原地址观看!!! 文章原地址:https://blog.csdn.net/m6i37jk/article/details/78140159 作者 ...
- zabbix-自定义监控项
一.自定义一个监控项 模板虽好,但是不能解决所有的监控,有些需要的监控项在模板中并没有,需要我们自己定义一个监控项,如何定义一个监控项呢?大概的流程是这样的几步 .在插件配置文件中定义一个key/va ...
- python数据写入Excel表格
from openpyxl import Workbook def main(): sheet_name = "表名1" row_count = 6 # 行数 info_resul ...
- Docker pull下载出现 error pulling image configuration:
出现这个问题,并且在错误信息的最后附带 net/http: TLS handshake timeout: 猜测是docker的相关配置问题,导致无法通过TLS握手 执行如下命令修改配置 echo &q ...