BZOJ 4764: 弹飞大爷
4764: 弹飞大爷
Time Limit: 30 Sec Memory Limit: 256 MB
Submit: 4 Solved: 4
[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
HINT
Source
今天偶然看到了某童鞋的弹飞绵羊的分块做法,十分不爽,想法卡他,然后就有了这道题,反正我觉得原来的分块方法是绝望了。但是万万木有想到,这道题依然有非LCT做法,比如大爷的Split Treap做法等等。
作为此题的出题人之一,其实我只负责题面部分和代码,解法都是ZZ和LH想的,和我没有半毛钱关系。
考虑怎么继续沿用弹飞绵羊的LCT做法,发现可能产生环,很烦。但是可以通过把环上的一条断掉,使得其在LCT中仍然是一棵树,我们把这条被“隐藏”起来的边标记在该树的Root上。那么每次加入边的时候,现考虑一下是否会形成环,如果会,就按照上面的方法处理。然后还有断边操作,只需要考虑一下断掉这条边后,是否会使得Root上的隐藏边重新显现即可。
不爽的是,刚刚放到大视野上一个下午,std就被LincHpin和Claris踩了。开心的是,至少我数据应该没造错。
#include <bits/stdc++.h> const int mxn = ; int tag[mxn];
int rev[mxn];
int siz[mxn];
int fat[mxn];
int son[mxn][]; inline bool isRoot(int t)
{
int f = fat[t]; if (!f)
return true; if (son[f][] == t)
return false;
if (son[f][] == t)
return false; return true;
} inline void update(int t)
{
siz[t] = ; if (son[t][])
siz[t] += siz[son[t][]];
if (son[t][])
siz[t] += siz[son[t][]];
} inline void connect(int f, int t, int s)
{
if (t)
fat[t] = f;
if (f)
son[f][s] = t;
} inline void rotate(int t)
{
int f = fat[t];
int g = fat[f];
int s = son[f][] == t; connect(f, son[t][!s], s);
connect(t, f, !s); fat[t] = g;
if (g && son[g][] == f)
son[g][] = t;
if (g && son[g][] == f)
son[g][] = t; update(f);
update(t);
} inline void push(int t)
{
if (rev[t])
{
rev[t] = ; if (son[t][])
rev[son[t][]] ^= ;
if (son[t][])
rev[son[t][]] ^= ; std::swap(son[t][], son[t][]);
}
} inline void pushdown(int t)
{
static int stk[mxn], tot; stk[++tot] = t; while (!isRoot(t))
stk[++tot] = t = fat[t]; while (tot)push(stk[tot--]);
} inline void splay(int t)
{
pushdown(t); while (!isRoot(t))
{
int f = fat[t];
int g = fat[f]; if (isRoot(f))
rotate(t);
else
{
int a = f && son[f][] == t;
int b = g && son[g][] == f; if (a == b)
rotate(f), rotate(t);
else
rotate(t), rotate(t);
}
}
} inline void access(int t)
{
int q = t; for (int p = ; t; p = t, t = fat[t])
splay(t), son[t][] = p, update(t); splay(q);
} inline void makeRoot(int t)
{
access(t), rev[t] ^= ;
} inline void link(int t, int f)
{
makeRoot(t), fat[t] = f;
} inline void cut(int t)
{
access(t);
fat[son[t][]] = ;
son[t][] = ;
update(t);
} inline int find(int t)
{
access(t); int p = t; while (son[p][])
p = son[p][]; return p;
} inline void Link(int t, int f)
{
if (t == f)
{
tag[t] = f;
return;
} if (find(t) != find(f))
link(t, f);
else
makeRoot(t), tag[t] = f;
} inline void change(int t, int f)
{
access(t); int p = find(t); if (!tag[p])
cut(t), Link(t, f);
else
{
if (t == p)
{
tag[p] = ;
Link(t, f);
}
else
{
int k = tag[p]; cut(t), Link(t, f); if (find(k) != find(p))
link(p, k), tag[p] = ;
}
}
} int n, m, s[mxn]; signed main(void)
{
scanf("%d%d", &n, &m); for (int i = ; i <= n; ++i)
scanf("%d", s + i); for (int i = ; i <= n; ++i)
{
int t = i + s[i]; if (t < )
Link(i, n + );
else if (t > n)
Link(i, n + );
else
Link(i, t);
} for (int i = ; i <= m; ++i)
{
int opt; scanf("%d", &opt); if (opt == )
{
int t; scanf("%d", &t); int p = find(t); if (tag[p])
puts("-1");
else
{
makeRoot(n + ), access(t);
printf("%d\n", siz[son[t][]]);
}
}
else
{
int a, b; scanf("%d%d", &a, &b); s[a] = b; int t = a + b; if (t < )
change(a, n + );
else if (t > n)
change(a, n + );
else
change(a, t);
}
}
}
@Author: YouSiki
BZOJ 4764: 弹飞大爷的更多相关文章
- BZOJ 4764: 弹飞大爷 LCT
思路并不难,主要是细节需要注意一下. 在 lct 中,删边要写成:f[lson]=0,lson=0 (因为删 x->y 时 y 不一定是左儿子,y 只是 x 的前驱) 然后 f[lson]=ls ...
- 【BZOJ】4764: 弹飞大爷 LCT
[题意]给定n个数字ai,表示大爷落到i处会被弹飞到i+ai处,弹飞到>n或<1处则落地.m次操作,修改一个ai,或询问大爷落到x处经过几次落地(或-1).n,m<=10^5,|ai ...
- 【LCT维护基环内向树森林】BZOJ4764 弹飞大爷
4764: 弹飞大爷 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 101 Solved: 52[Submit][Status][Discuss] ...
- 【BZOJ4764】弹飞大爷 LCT
[BZOJ4764]弹飞大爷 Description 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们决定齐心合力构造一个下面这样的序列.这个序列 ...
- 【bzoj 4764】弹飞大爷
Description 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们决定齐心合力构造一个下面这样的序列.这个序列共有N项,每项都代表了一个小伙 ...
- BZOJ4764弹飞大爷——LCT
题目描述 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们 决定齐心合力构造一个下面这样的序列.这个序列共有N项,每项都代表了一个小伙伴的力量值, ...
- bzoj4764: 弹飞大爷
Description 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们 决定齐心合力构造一个下面这样的序列.这个序列共有N项,每项都代表了一个小 ...
- [bzoj] 2002 弹飞绵羊 || LCT
原题 简单的LCT练习题. 我们发现对于一个位置x,他只能跳到位置x+k,也就是唯一的父亲去.加入我们将弹飞的绵羊定义为跳到了n+1,那么这就形成了一棵树.而因为要修改k,所以这颗树是动态连边的,那么 ...
- bzoj 2002: 弹飞绵羊 Link-Cut-Tree
题目: Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置, ...
随机推荐
- 【转】深入理解C++的动态绑定和静态绑定 & 不要重定义虚函数中的默认参数
为了支持c++的多态性,才用了动态绑定和静态绑定.理解他们的区别有助于更好的理解多态性,以及在编程的过程中避免犯错误.需要理解四个名词:1.对象的静态类型:对象在声明时采用的类型.是在编译期确定的.2 ...
- 2017-2018 Exp8 Web基础 20155214
目录 Exp8 Web基础 实验内容 建站过程 SQL注入 知识点 Exp8 Web基础 实验内容 实验环境 主机 Kali 靶机 Kali 实验工具 后台语言 'PHP' 服务器 'Apache' ...
- 20155216 Exp4 恶意代码分析
20155216 Exp4 恶意代码分析 实践内容 使用schtasks指令监控系统运行 先在C盘目录下建立一个netstatlog.bat文件和netstatlog.txt文件,将记录的联网结果格式 ...
- 20155338《网络对抗》Exp3 免杀原理与实践
20155338<网络对抗>Exp3 免杀原理与实践 实验过程 一.免杀效果参考基准 Kali使用上次实验msfvenom产生后门的可执行文件,上传到老师提供的网址http://www.v ...
- EZ 2018 04 13 NOIP2018 模拟赛(八)
这次的题目都是什么鬼? 玄学乱搞+肉眼看CODE+倒着搜索? 好吧是我ZZ了 链接在此 T1 玄学乱搞 由于考场上写的部分分做法忘记讨论n<=2000时的情况,少得了30pts 很容易得到一个基 ...
- OLEDB 命令转换组件的用法
在数据流任务组件中,OLEDB 命令转换组件对输入的每行数据调用TSQL,该组件能够把输入的数据作为参数,因此,该转换组件主要用于运行参数化的查询. 命令转换组件的配置十分简单,只有三个可编辑属性,位 ...
- C语言与数据库操作入门(Win版)
C语言与数据库操作入门(Win版) 2017年12月10日 17:30:17 阅读数:1387 数据库,DataBase,学C语言的是不是想说,很想爱她却并不容易呢?不用着急,C语言也可以操作数据库的 ...
- Monkey基本使用
什么是 Monkey Monkey 是一个 Android 自动化测试小工具.主要用于Android 的压力测试, 主要目的就是为了测试app 是否会Crash. Monkey 特点 顾名思义,Mon ...
- EntityFramework Core 2.x (ef core) 在迁移中自动生成数据库表和列说明
在项目开发中有没有用过拼音首字母做列名或者接手这样的项目? 看见xmspsqb(项目审批申请表)这种表名时是否有一种无法抑制的想肛了取名的老兄的冲动? 更坑爹的是这种数据库没有文档(或者文档老旧不堪早 ...
- PHP学习 安装环境和语法学习
要回归技术了,昨天下午专门去深圳大学城图书馆借书,甚是漂亮 禁不住搞了几张照片 在图书馆里面的书真多,图书馆环境真好,清华大学 北京大学研究生院的学生们有福了,最后一句深圳政府真尼玛有钱,下图是图书馆 ...