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. 考虑新加进来一条边,想要让它能够减少一个联通块的条件就是现在边的两个端点还没有联通. 如果联通 ...
随机推荐
- Python3 和 Python2的区别
目录 print Python2.7的print不是一个function Python3里的print是一个function. Unicode Python 2 有 ASCII str() 类型,un ...
- 一个农民工自学java找到工作的励志故事
<!-----------------------------------------------------------------------------摘自网络-------------- ...
- mysql常见内置函数
在mysql中有许多内置的函数,虽然功能都能在PHP代码中实现,但巧妙的应用mysql内置函数可以大大的简化开发过程,提高效率. 在这里我总结一下一些常用的,方便以后查看: mysql字符串函数: c ...
- deferred.promise.then().then()异步链式操作(Chain operation)
//deferred.promise.then().then() deferred.promise.then(function () { console.log('1 resolve'); retur ...
- Java ShellSort
Java ShellSort /** * <html> * <body> * <P> Copyright 1994-2018 JasonInternational ...
- Html 中scroll offset client 总结
HTML精确定位:scrollLeft,scrollWidth,clientWidth,offsetWidth scrollHeight: 获取对象的滚动高度. scrollLeft:设置或获取位于对 ...
- 3d转化
3d转化 想要实现3d效果,首先要确定的是观察点,这是2d转换所不需要的.具体的我也看的很糊涂,美术什么的根本不懂好吗. 但有些东西是确定的,perspective定义的是3d元素距视图的距离,因此像 ...
- js原生方法的重写
讲干货,不啰嗦,通过prototype可以获取到JavaScript的原型对象,进而可以在对象原型上添加新的属性和方法,当该方法与原方法名称一样时会覆盖原方法既:重写,当不一样时既:添加 如:实现数组 ...
- 你所不知道的 Console
1.凡人视角 打印字符串 代码: console.log("I am a 凡人"); 打印提示消息 代码: console.info("Yes, you arm a 凡人 ...
- Java 之 JDK9 对集合添加的优化
通常,在代码中创建一个集合(例如,List 或 Set ),并直接用一些元素填充它. 实例化集合,几个 add方法调用,使得代码重复. Java 9,添加了几种集合工厂方法,更方便创建少量元素的集合. ...