【题意概述】

  给一棵以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. KeepAlived的配置

    KeepAlived的相关配置 KeepAlived 配置 参考帮助 man keepalived.conf 配置文件组件部分: top hierachy(层次) global configurati ...

  2. sqlserver2000连接失败,不存在或拒绝访问

    一 看ping 服务器IP能否ping通. 这个实际上是看和远程sql server 2000服务器的物理连接是否存在.如果不行,请检查网络,查看配置,当然得确保远程sql server 2000服务 ...

  3. hdu1512 Monkey King(并查集,左偏堆)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1512 题目大意:有n个猴子,一开始每个猴子只认识自己.每个猴子有一个力量值,力量值越大表示这个猴子打架 ...

  4. 使用 script 的 module 属性实现 es6 以上的兼容

    几个月前看到了这篇文章 https://philipwalton.com/articles/deploying-es2015-code-in-production-today/,给了我很大的启发,本来 ...

  5. [SDOI2010]外星千足虫(高斯消元)

    高斯消元裸题... 方法一:暴力,O(2^n)20分 方法二:直接Gauss,加点玄学技巧搞得好的话70分 方法三:使用bitset优化,复杂度:$O(\frac{n^3}{ω})$ 不会的同学看一下 ...

  6. c++ isdigit函数

    函数名:isdigit 函数所需头文件:#include<cstdio> 函数格式:isdigit(字符) 函数作用:判断括号内是否为1~9的数字. 例:isdigit(4) 就是true ...

  7. TCP流量控制与拥塞解决

    滑动窗口 但要提高网络利用率: nagle算法 - 延迟 慢启动.拥塞避免 发送端主导cwnd init  set  ssthresh  &  cwnd = swnd loop : 网不阻塞 ...

  8. RabbitMQ~广播消息

    定义 广播消息是指生产者产生的消息将分发给所有订阅这个消息的消费者,而普通的模式是:一批消息可以被多个人共同消费,如consumer1可能消费1,3,5记录,而consumer2可能消费的是2,4,6 ...

  9. SQL server存储过程及触发器基础

    存储过程:就像函数一样的会保存在数据库中-->可编程性 --> 存储过程-----------------------------------------------------创建存储过 ...

  10. CF540C Ice Cave

    思路: 搜索. 加回溯会超时,不加回溯就过了,不是很理解. 实现: #include <iostream> #include <cstdio> using namespace ...