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. 考虑新加进来一条边,想要让它能够减少一个联通块的条件就是现在边的两个端点还没有联通. 如果联通 ...
随机推荐
- spring cloud微服务实践三
上篇文章里我们实现了spring cloud中的服务提供者和使用者.接下来我们就来看看spring cloud中微服务的其他组件. 注:这一个系列的开发环境版本为 java1.8, spring bo ...
- SAS学习笔记38 SAS Comments注释语句
通常来讲,注释语句有四种: 1.* message; 2.COMMENT message; 3./* message */ 4.%* message; 第一种的主要限制是注释之中不得有“:”符号.通常 ...
- java中针对 try和finally一些总结
结论 1.不管有没有异常,finally中的代码都会执行 2.当try.catch中有return时,finally中的代码依然会继续执行 3.finally是在return后面的表达式运算之后执行的 ...
- VS2019打开项目加载失败:无法找到 .NET Core SDK。请检查确保已安装此项且 global.json 中指定的版本(如有)与所安装的版本相匹配。
问题描述: 用VS2019创建了asp.net core项目,正常运行:过几天后,再次打开,发现无法加载项目,报错无法找到.net core sdk. 分析过程: 首先怀疑环境变量的问题,重新设置 ...
- 11. Java方法的定义与使用
1.1方法的定义 方法是一段可以被重复调用的代码块. 方法的声明: public static 方法返回值 方法名称 ([参数类型 变量...]) 方法体代码: [return 返回值]: 当方法以v ...
- swith-case 日历
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Input system (输入子系统)
Input system (输入子系统) 以前写一些输入设备(键盘,鼠标等)的驱动都是字符设备,混杂设备处理的,linux开源社区的大神门看到了这大量的输入设备如此分散不堪,就想有木有一种机制,可以对 ...
- 什么是mvvm设计模式
目前比较流行的几个框架,例如vue.js.react.js.avalon.angular.js等,给自己的定位都是属于mvvm类型框架,那么什么是mvvm框架呢?mvvm是什么意思呢? 聊到mvvm就 ...
- crunch离线密码生成
Crunch是一种创建密码字典工具,按照指定的规则生成密码字典,可以灵活的制定自己的字典文件. 一.Crunch为kali自带工具之一在kali环境下进行,默认基于26个小写英文字母. 语法:cru ...
- ARP、Proxy ARP、Gratuitous ARP
Proxy ARP 什么是Proxy ARP? 一个主机A(通常是路由器)有意应答另一个主机B的ARP请求(ARP requests).主机A通过伪装其身份,承担起将分组路由到真实目的地的责任.代理A ...