【LCT维护基环内向树森林】BZOJ4764 弹飞大爷
4764: 弹飞大爷
Time Limit: 30 Sec Memory Limit: 256 MB
Submit: 101 Solved: 52
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
1 1 1
1 1
1 2
1 3
2 1 2
1 1
1 2
1 3
2 3 -1
1 1
1 2
1 3
2 2 233
1 1
1 2
1 3
2 2 -233
1 1
1 2
1 3
Sample Output
3
2
1
2
2
1
-1
-1
-1
3
1
2
3
1
2
题解
LCT维护基环内向树森林
具体来说,就是当我们原来维护的无向图变成了一个每个点出度为1的有向图
显然它是可能存在环的,并且更重要的是它不能换根(方向问题)
所以若它是一棵树的话,正常维护LCT
如果它形成了环,我们记一下这个联通块的根到达的点的位置pos[i]
对于Link操作,我们判断一下这条有向边x--->y的端点y在被连接之前的根节点是否已经可以是x
- 如果是,那么加上这条边之后形成环,我们显然不能把它加上,所以我们令pos[x]=y
- 如果不是,正常地把x连到y的下面
对于Cut操作,我们要判断一下这条有向边x--->y的端点x形成的环是否正好连到y,即判断pos[x]是否等于y
- 如果是,那么直接把环去掉,即令pos[x]=0
- 如果不是,我们先记一下x在联通块中的根节点rt,然后正常地去掉这条边
- 但是然后我们还要判断一下割断这条边后是否会保留原来的环,如果已经没环,就把记录的边加上,如果环还在,退出
具体看代码吧
代码
//by 减维
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<bitset>
#include<set>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<ctime>
#include<algorithm>
#define ll long long
#define il inline
#define rg register
#define db double
#define mpr make_pair
#define maxn 200005
#define inf (1<<30)
#define eps 1e-8
#define pi 3.1415926535897932384626L
using namespace std; inline int read()
{
int ret=;bool fla=;char ch=getchar();
while((ch<''||ch>'')&&ch!='-')ch=getchar();
if(ch=='-'){fla=;ch=getchar();}
while(ch>=''&&ch<=''){ret=ret*+ch-'';ch=getchar();}
return fla?-ret:ret;
} int n,m,fa[maxn],son[maxn][],siz[maxn],rev[maxn],pos[maxn];
int a[maxn]; il bool pdp(int x){return son[fa[x]][]==x;}
il bool isrt(int x){return son[fa[x]][]!=x&&son[fa[x]][]!=x;}
il void rever(int x){rev[x]^=;swap(son[x][],son[x][]);}
il void upda(int x){siz[x]=siz[son[x][]]+siz[son[x][]]+;} il void pdn(int x)
{
if(rev[x])
{
if(son[x][]) rever(son[x][]);
if(son[x][]) rever(son[x][]);
rev[x]=;
}
} void pd(int x){if(!isrt(x)) pd(fa[x]);pdn(x);} il void rot(int x)
{
int f=fa[x],g=fa[f],o=pdp(x);
if(!isrt(f)) son[g][pdp(f)]=x;fa[x]=g;
son[f][o]=son[x][!o];fa[son[f][o]]=f;
son[x][!o]=f;fa[f]=x;
upda(f),upda(x);
} il void splay(int x)
{
pd(x);
for(;!isrt(x);rot(x))
if(!isrt(fa[x])) rot(pdp(fa[x])==pdp(x)?fa[x]:x);
} il void acc(int x)
{
for(int y=;x;y=x,x=fa[x])
splay(x),son[x][]=y,upda(x);
} il int find(int x)
{
acc(x),splay(x);
while(son[x][]) pdn(x),x=son[x][];
return x;
} il void link(int x,int y)
{
if(find(y)==x) pos[x]=y;
else acc(x),splay(x),fa[x]=y;
} il void cut(int x,int y)
{
if(pos[x]==y) pos[x]=;
else{
int t=find(x);
acc(x),splay(x),fa[son[x][]]=,son[x][]=,upda(x);
if(pos[t]&&find(pos[t])!=t) link(t,pos[t]),pos[t]=;
}
} int main()
{
n=read(),m=read();
for(int i=;i<=n;++i) a[i]=read(),siz[i]=;
for(int i=;i<=n;++i)
if(i+a[i]>=&&i+a[i]<=n) link(i,a[i]+i);
for(int i=,op,x,y;i<=m;++i)
{
op=read(),x=read();
if(op==){
acc(x),y=find(x);
if(pos[y]) puts("-1");
else splay(x),printf("%d\n",siz[x]);
}else{
y=read();
if(x+a[x]>=&&a[x]+x<=n) cut(x,a[x]+x);
if(x+y>=&&x+y<=n) link(x,x+y);
a[x]=y;
}
}
return ;
}
【LCT维护基环内向树森林】BZOJ4764 弹飞大爷的更多相关文章
- bzoj4764 弹飞大爷 LCT
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4764 题解 如果 \(a_i > 0\) 的话,那么就是 bzoj2002 的原题.直接 ...
- BZOJ4764弹飞大爷——LCT
题目描述 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们 决定齐心合力构造一个下面这样的序列.这个序列共有N项,每项都代表了一个小伙伴的力量值, ...
- bzoj4764: 弹飞大爷
Description 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们 决定齐心合力构造一个下面这样的序列.这个序列共有N项,每项都代表了一个小 ...
- bzoj4764: 弹飞大爷 link-cut-tree
题目传送门 这道题啊 调了一个晚上 因为写的是一个有根树和n个基环的写法 所以写得很奇怪..... 最后发现单独处理树的时候不能随意改变S(就是原来的根)不然size会出错.... #include& ...
- 【BZOJ4764】弹飞大爷 LCT
[BZOJ4764]弹飞大爷 Description 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们决定齐心合力构造一个下面这样的序列.这个序列 ...
- HDU6370 Werewolf 【基环内向树】
HDU6370 Werewolf 题意: 有\(N\)个人玩狼人杀,只有村民和狼人,每个人指定另一个人并指出一个身份,其中:村民是不会说谎的,狼人是有可能说谎的,问在所有情况下必然是狼人的人数和必然是 ...
- 【BZOJ】4764: 弹飞大爷 LCT
[题意]给定n个数字ai,表示大爷落到i处会被弹飞到i+ai处,弹飞到>n或<1处则落地.m次操作,修改一个ai,或询问大爷落到x处经过几次落地(或-1).n,m<=10^5,|ai ...
- BZOJ 4764: 弹飞大爷
4764: 弹飞大爷 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 4 Solved: 4[Submit][Status][Discuss] Des ...
- P3703 [SDOI2017]树点涂色 LCT维护颜色+线段树维护dfs序+倍增LCA
\(\color{#0066ff}{ 题目描述 }\) Bob有一棵\(n\)个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点 ...
随机推荐
- 深入理解计算机系统_3e 第六章家庭作业 CS:APP3e chapter 6 homework
6.22 假设磁道沿半径均匀分布,即总磁道数和(1-x)r成正比,设磁道数为(1-x)rk: 由题单个磁道的位数和周长成正比,即和半径xr成正比,设单个磁道的位数为xrz: 其中r.k.z均为常数. ...
- Intellij IDEA 4种配置热部署的方法
热部署可以使的修改代码后,无须重启服务器,就可以加载更改的代码. 第1种:修改服务器配置,使得IDEA窗口失去焦点时,更新类和资源 菜单Run -> EditConfiguration , 然后 ...
- Python3入门笔记(1) —— windows安装与运行
Python的设计哲学是"优雅"."明确"."简单".这也是我喜欢Python的理由之一 Python的安装: 1.进入Python官方网站 ...
- iOS开发--数据库管理CoreData的使用
CoreData是iOS5后,苹果提供的原生的用于对象化管理数据并且持久化的框架.CoreData本质上是将底层数据库封装成对象进行管理.但数据库实际上只是CoreData的一个功能,并不是全部功能. ...
- go实例之轻量级线程goroutine、通道channel与select
1.goroutine线程 goroutine是一个轻量级的执行线程.假设有一个函数调用f(s),要在goroutine中调用此函数,请使用go f(s). 这个新的goroutine将与调用同时执行 ...
- IntelliJ IDEA如何设置头注释,自定义author和date
下面这张图,保证你一看就会: 下面这个模板,你拿去改一改就行了. /** * @Author: Gosin * @Date: ${DATE} ${TIME} */ 如果觉得上面名字下面的波浪线碍眼,可 ...
- find 命令详解
find 作用:用于在文件树种查找文件,并作出相应的处理 (硬盘) 格式:find pathname -options [-print -exec -ok ...] 格式参数:pathname: fi ...
- 2、各种折腾,安装交叉环境的gcc和qt,测试c++和qt程序
本博文仅作本人操作过程的记录,留作备忘.自强不息 QQ1222698 1.安装gcc和qt 把光盘里带的gcc-4.4.4-glibc-2.11.1-multilib-1.0_EasyARM-iMX2 ...
- find 命令的误差估值与单位调整
一.命令简介 find 命令的 -size 参数 单位b(不是byte而是block).c.w.k.M.G.默认是单位b ,也就是1block = 512byte = 0.5kb (文件系统ext4) ...
- java数组去重
java数组去重 1.创建新数组,用于保存比较结果 2.设定随机数组最大最小值 3.开始去重 4.计算去重所需时间 package org.zheng.collection; import java. ...