【题意概述】

  给一棵以1为根的树,树上的每个节点有一个ai值,代表它可以传送到自己的ai倍祖先,如果不存在则传送出这棵树。现在询问某个节点传送出这棵树需要多少步。

【题解】

  其实是把“弹飞绵羊”那道题从序列上搬到了树上,解法其实类似。

  我们可以用LCT维护传送的关系,若点i存在ai倍祖先,那么就把他们link起来,否则就把i与特殊节点n+1给link起来。

  询问某个点要传送多少次时,就是询问这个点到n+1有多远,我们在LCT上取出这一段,查询size即可。

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N (100010)
#define ls (c[u][0])
#define rs (c[u][1])
#define LL long long
#define rg register
using namespace std;
int T,n,m,opt,cnt,tot,last[N],k[N],dfn[N],dep[N],p[N][];
struct edge{
int to,pre;
}e[N];
char buf[],*ptr=buf-;
template<typename T>
inline void read(T &k)
{
int f=; k=; char c=*++ptr;
while(c<'' || c>'') c=='-'&&(f=-), c=*++ptr;
while(c<='' && c>='') k=k*+c-'', c=*++ptr;
k*=f;
} struct Link_Cut_Tree{
int top,c[N][],fa[N],rev[N],size[N],q[N];
inline void clear(){
for(rg int i=;i<=n+;i++) c[i][]=c[i][]=size[i]=rev[i]=fa[i]=;
}
inline void pushdown(int u){
if(rev[u]) rev[ls]^=,rev[rs]^=,rev[u]^=,swap(ls,rs);
}
inline void pushup(int u){
size[u]=;
if(ls) size[u]+=size[ls];
if(rs) size[u]+=size[rs];
}
inline bool isroot(int u){
return c[fa[u]][]!=u&&c[fa[u]][]!=u;
}
inline bool which(int u){
return c[fa[u]][]==u;
}
void rotate(int u){
int f=fa[u],gf=fa[f],wh=which(u);
if(!isroot(f)) c[gf][which(f)]=u;
fa[u]=gf; fa[f]=u; fa[c[u][wh^]]=f;
c[f][wh]=c[u][wh^]; c[u][wh^]=f;
pushup(f); pushup(u);
}
void splay(int u){
q[top=]=u;
for(int i=u;!isroot(i);i=fa[i]) q[++top]=fa[i];
for(int i=top;i;i--) pushdown(q[i]);
while(!isroot(u)){
if(!isroot(fa[u])) rotate(which(u)==which(fa[u])?fa[u]:u);
rotate(u);
}
pushup(u);
}
void access(int u){
for(int son=;u;son=u,u=fa[u])
splay(u),c[u][]=son,pushup(u);
}
void makeroot(int u){
access(u); splay(u); rev[u]^=;
}
int find(int u){
access(u); splay(u);
while(ls) u=ls; splay(u);
return u;
}
void split(int x,int y){
makeroot(x); access(y); splay(y);
}
void cut(int x,int y){
int xrt=find(x),yrt=find(y);
if(xrt!=yrt) return;
split(x,y);
if(c[y][]==x) c[y][]=,fa[x]=;
pushup(y);
}
void link(int x,int y){
int xrt=find(x),yrt=find(y);
if(xrt==yrt) return;
makeroot(x); fa[x]=y;
}
}t;
void dfs(int x,int fa){
dfn[x]=++cnt; dep[x]=dep[fa]+; p[x][]=fa;
int tmp=log2(dep[x]);
for (int i=;i<=tmp;i++) p[x][i]=p[p[x][i-]][i-];
for(rg int i=last[x];i;i=e[i].pre) dfs(e[i].to,x);
}
inline int anc(int x,int y){
for(rg int i=;i<=;i++) if(y&(<<i)) x=p[x][i];
return x;
}
inline void Pre(){
for(rg int i=;i<=n;i++) last[i]=;
cnt=tot=;
t.clear();
}
int main(){
fread(buf, , sizeof(buf), stdin);
read(T);
while(T--){
read(n);
Pre();
for(rg int i=;i<=n;i++){
int fa; read(fa);
e[++tot]=(edge){i,last[fa]}; last[fa]=tot;
}
dfs(,);
// for(rg int i=1;i<=n;i++) printf("%d ",dep[i]); puts("dep");
for(rg int i=;i<=n;i++){
read(k[i]);
if(k[i]>=dep[i]) t.link(dfn[i],n+);
else t.link(dfn[i],dfn[anc(i,k[i])]);
}
read(m);
while(m--){
int opt; read(opt);
if(opt==){
int x; read(x);
x=dfn[x];
t.makeroot(x); t.access(n+); t.splay(n+);
printf("%d\n",t.size[n+]-);
}
else{
int x,y; read(x); read(y);
if(k[x]>=dep[x]&&y>=dep[x]) continue;
if(k[x]>=dep[x]) t.cut(dfn[x],n+);
else t.cut(dfn[x],dfn[anc(x,k[x])]);
k[x]=y;
if(k[x]>=dep[x]) t.link(dfn[x],n+);
else t.link(dfn[x],dfn[anc(x,k[x])]);
}
}
}
return ;
}

ACM多校联赛7 2018 Multi-University Training Contest 7 1009 Tree的更多相关文章

  1. 2018牛客网暑假ACM多校训练赛(第三场)G Coloring Tree 计数,bfs

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round3-G.html 题目传送门 - 2018牛客多校赛第三场 G ...

  2. 牛客网暑期ACM多校训练营(第三场)G:Coloring Tree(函数的思想)

    之前两次遇到过函数的思想的题,所以这次很敏感就看出来了.可以参考之前的题: https://www.cnblogs.com/hua-dong/p/9291507.html Christmas is c ...

  3. hdu 6394 Tree (2018 Multi-University Training Contest 7 1009) (树分块+倍增)

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=6394 思路:用dfs序处理下树,在用分块,我们只需要维护当前这个点要跳出这个块需要的步数和他跳出这个块去 ...

  4. 2018 Nowcoder Multi-University Training Contest 2

    目录 Contest Info Solutions A. run D. monrey G. transform H. travel I. car J. farm Contest Info Practi ...

  5. 2018 Nowcoder Multi-University Training Contest 1

    Practice Link J. Different Integers 题意: 给出\(n\)个数,每次询问\((l_i, r_i)\),表示\(a_1, \cdots, a_i, a_j, \cdo ...

  6. 2018 Nowcoder Multi-University Training Contest 5

    Practice Link A. gpa 题意: 有\(n\)门课程,每门课程的学分为\(s_i\),绩点为\(c_i\),要求最多删除\(k\)门课程,使得gpa最高. gpa计算方式如下: \[ ...

  7. 2018 Nowcoder Multi-University Training Contest 10

    Practice Link J. Rikka with Nickname 题意: 给出\(n\)个字符串,要求依次合并两个串\(s, t\),满足将\(t\)合并到\(s\)中变成\(r\),使得\( ...

  8. 2018牛客网暑期ACM多校训练营(第二场)I- car ( 思维)

    2018牛客网暑期ACM多校训练营(第二场)I- car 链接:https://ac.nowcoder.com/acm/contest/140/I来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 ...

  9. 2015 HDU 多校联赛 5363 Key Set

    2015 HDU 多校联赛 5363 Key Set 题目: http://acm.hdu.edu.cn/showproblem.php? pid=5363 依据前面给出的样例,得出求解公式 fn = ...

随机推荐

  1. Enum类的非一般用法汇总(工作中遇到时持续更新)

    1.  每个枚举实例定义一套自己的方法示例: 1 @AllArgsConstructor 2 public enum BroadcastTypeEnum { 3 ALL(0, "全站&quo ...

  2. AutoCAD2013 以上利用AccoreConsole+ c# NetApi 批量处理图纸

    AccoreConsole听起来有点拗口,其中文名可以叫做AutoCAD控制台或者无头AutoCAD.一句话概括,它是快速启动AutoCAD运行微环境,高效的处理图纸.你可以如同DOS命令行一样操作命 ...

  3. 在sql语句中使用关键字

    背景 开发过程中遇到了遇到了一句sql语句一直报错,看了一下字段名和表名都对应上了,但是还是一直报错 sql语句如下: update table set using = ""hh ...

  4. gauge自动化测试框架(二)

    Gauge通过Markdown来描述行为,所以我还需先学习学习Markdown语法,看了一下,还好,十来分钟应该就可以搞定.具体学习见另一篇文章

  5. win7任务计划提示”该任务映像已损坏或已篡改“怎么处理

    https://jingyan.baidu.com/article/e75057f2038e2febc91a8915.html 在命令行窗口(cmd)执行命令:schtasks /query /v   ...

  6. 常用的几个Dos命令-持续更新中

    1.服务相关 (1).查看服务 C:\Windows\system32>net start 已经启动以下 Windows 服务: (2).启动服务 C:\Windows\system32> ...

  7. EasyUI系列学习(十)-Tabs(选项卡)

    一.创建组件 <div class="easyui-tabs" style="width:500px;height:250px"> <div ...

  8. FCC 基础JavaScript 练习3

    1.通过使用提供的变量参数:名词myNoun.形容词myAdjective.动词myVerb.副词myAdverb,来创建一个新的句子 result, function wordBlanks(myNo ...

  9. JavaScript(十四)经典的Ajax

    (function(){ //唯一向外暴露一个顶层变量 var myajax = window.myajax = {}; //作者.版本号信息 myajax.author = "maxwel ...

  10. 【笔记JS/HTML/CSS】用div实现个性化button,背景半透明

    html中的button默认样式..不太能看,如果调一调背景色和字体的话也挺适合简洁的页面设计 于是决定配合JS,用html中的div完成button 最终结果图: html代码:(first_pas ...