链接: http://acm.hdu.edu.cn/showproblem.php?pid=6394

思路:用dfs序处理下树,在用分块,我们只需要维护当前这个点要跳出这个块需要的步数和他跳出这个块去到的下一个点的下标,这样更新和询问的复杂度就降到了sqrt(n),查询树上的点的时候我们可以用倍增来降时间复杂度,这样处理下就不会超时了,。

介绍下代码主要数组的作用方便看懂代码;
l[i] : 当前块的左边界

r[i]:当前块的右边界

num[i]: 当前点需要多少步跳出这个块

pre[i]: 这个点跳出这个块后到达的点的下标,因为是倒着跳的,pre储存的值是跳出当前块跳到上一个块到达的点的下标。

tid[i]: 当前点的dfs序

Next[i]: 因为是倒着跳的(从i点往前跳直到跳出这棵树),Next储存的是当前点下一步回跳到的点的下标。

实现代码:

#include<bits/stdc++.h>
using namespace std;
const int M = 1e5 + ;
int w[M],f[][M],n,q,head[M],pre[M],cnt,idx,num[M],Next[M],tid[M];
int block,blo[M],l[M],r[M];
struct node{
int to,next;
}e[M];
void init(){
cnt = ;
idx = ;
memset(head,,sizeof(head));
} void add(int u,int v){
e[++cnt].to = v;e[cnt].next = head[u];head[u] = cnt;
} void dfs(int u,int fa){ //dfs序
f[][u] = fa; tid[u] = ++idx;
for(int i = head[u];i;i = e[i].next){
dfs(e[i].to,u);
}
} int find(int x,int l){ //x向上走l步会走到哪里
for(int i = ;i >= ;i--){
if((l>>i)&)
x = f[i][x];
}
return x;
} void dfs1(int u){ //初始化
int p = find(u,w[u]);
Next[tid[u]] = tid[p];
if(tid[p] < l[blo[tid[u]]]) num[tid[u]]=,pre[tid[u]] = tid[p];
else num[tid[u]] = num[tid[p]]+,pre[tid[u]] = pre[tid[p]];
for(int i = head[u];i;i=e[i].next){
dfs1(e[i].to);
}
} void update(int x,int c){ //修改
int p = find(x,c); w[x] = c;
Next[tid[x]] = tid[p];
if(tid[p] < l[blo[tid[x]]]) num[tid[x]] = ,pre[tid[x]] = tid[p];
else num[tid[x]] = num[tid[p]]+, pre[tid[x]] = pre[tid[p]];
for(int i = tid[x]+;i <= r[blo[tid[x]]];i ++){
if(Next[i] >= l[blo[i]]){
num[i] = num[Next[i]] + ;
pre[i] = pre[Next[i]];
}
}
} int query(int x){ //查询
int ans = ;
while(x > ){
ans += num[x];
x = pre[x];
}
return ans;
} int main()
{
int t;
scanf("%d",&t);
while(t--){
init();
int x;
scanf("%d",&n);
for(int i = ;i <= n;i ++){
scanf("%d",&x);
add(x,i);
}
for(int i = ;i <= n;i ++)
scanf("%d",&w[i]);
dfs(,);
for(int i = ;i <= ;i ++)
for(int j = ;j <= n;j ++)
f[i][j] = f[i-][f[i-][j]];
block = sqrt(n);
for(int i = ;i <= n;i ++) blo[i] = (i-)/block+;
for(int i = ;i <= blo[n];i ++) l[i] = (i-)*block+,r[i]=i*block;
r[blo[n]] = n;
dfs1();
scanf("%d",&q);
while(q--){
int op,x,y;
scanf("%d %d",&op,&x);
if(op == ) printf("%d\n",query(tid[x]));
else scanf("%d",&y),update(x,y);
}
}
return ;
}

hdu 6394 Tree (2018 Multi-University Training Contest 7 1009) (树分块+倍增)的更多相关文章

  1. HDU 6395 2018 Multi-University Training Contest 7 (快速幂+分块)

    原题地址 Sequence Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)T ...

  2. hdu 4930 Fighting the Landlords--2014 Multi-University Training Contest 6

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4930 Fighting the Landlords Time Limit: 2000/1000 MS ...

  3. HDU 6143 - Killer Names | 2017 Multi-University Training Contest 8

    /* HDU 6143 - Killer Names [ DP ] | 2017 Multi-University Training Contest 8 题意: m个字母组成两个长为n的序列,两序列中 ...

  4. HDU 6074 - Phone Call | 2017 Multi-University Training Contest 4

    看标程的代码这么短,看我的.... 难道是静态LCA模板太长了? /* HDU 6074 - Phone Call [ LCA,并查集 ] | 2017 Multi-University Traini ...

  5. HDU 6068 - Classic Quotation | 2017 Multi-University Training Contest 4

    /* HDU 6068 - Classic Quotation [ KMP,DP ] | 2017 Multi-University Training Contest 4 题意: 给出两个字符串 S[ ...

  6. HDU 6076 - Security Check | 2017 Multi-University Training Contest 4

    /* HDU 6076 - Security Check [ DP,二分 ] | 2017 Multi-University Training Contest 4 题意: 给出两个检票序列 A[N], ...

  7. HDU 6071 - Lazy Running | 2017 Multi-University Training Contest 4

    /* HDU 6071 - Lazy Running [ 建模,最短路 ] | 2017 Multi-University Training Contest 4 题意: 四个点的环,给定相邻两点距离, ...

  8. HDU 6078 - Wavel Sequence | 2017 Multi-University Training Contest 4

    /* HDU 6078 - Wavel Sequence [ DP ] | 2017 Multi-University Training Contest 4 题意: 给定 a[N], b[M] 要求满 ...

  9. HDU 6070 - Dirt Ratio | 2017 Multi-University Training Contest 4

    比赛时会错题意+不知道怎么线段树维护分数- - 思路来自题解 /* HDU 6070 - Dirt Ratio [ 二分,线段树 ] | 2017 Multi-University Training ...

  10. HDU 6036 - Division Game | 2017 Multi-University Training Contest 1

    /* HDU 6036 - Division Game [ 组合数学,NTT ] | 2017 Multi-University Training Contest 1 题意: k堆石子围成一个圈,数量 ...

随机推荐

  1. C#连接数据库插入数据

    首先是安装JDBC操作数据库的包,,当然自己看着办哈,可以自己下载以后导入,或者直接让软件本身下载 第一种方式 第二种 咱自己下载个低版本的 点击这个链接 点击以后呢可以直接下载下来,然后导入(大家百 ...

  2. 11-(基础入门篇)WiFi模块开发,下载运行第一个程序

    https://www.cnblogs.com/yangfengwu/p/9954840.html 第一就是重新刷一下固件,咱们的固件保持一致,有问题好处理 先刷空固件 我用的 所以刷8Mbit的 给 ...

  3. SPOJ Qtree系列 5/7

    Qtree1 树剖裸题 注意把边权移到深度较深的点上,树剖跳的时候不要将LCA的答案统计上就行了 #include<stdio.h> #include<string.h> #d ...

  4. 解决webapi首次启动速度慢的问题 - z

    原理与下面两篇文章提及的相同 https://blog.csdn.net/godcyx/article/details/38517135 http://www.huaface.com/p/12

  5. TensorFlow框架下的RNN实践小结

    截至目前,TensorFlow的RNN APIs还处于Draft阶段.不过据官方解释,RNN的相关API已经出现在Tutorials里了,大幅度的改动应该是不大可能,现在入手TF的RNN APIs风险 ...

  6. .NET日志记录之——log4net划重点篇

    .NET日志记录之--log4net划重点篇 1.概述 log4net是.Net下一个非常优秀的开源日志记录组件.log4net记录日志的功能非常强大.它可以将日志分不同的等级,以不同的格式,输出到不 ...

  7. 【变态需求】bootstrapTable列排序-选择正序倒序不排序

    产品经理:那个table排序能不能点击后弹个选项选择正序倒序不排序? -- 那个是bootstrapTable的插件!不支持!改不了!! 注意:数据上假的,效果看http请求参数进行脑补 这是boot ...

  8. WPF 矩形框8个控制点伸缩及拖拽

    最近在研发图片控件矩形框8个控制点进行控制边框的大小.位置等信息,之前查阅了相关的信息,比如别人整合的类:ControlResizer 这个类虽然是好,但是很大程度上是有限制,换句话说,它需要你二次更 ...

  9. Vuex实现原理解析

    我们在使用Vue.js开发复杂的应用时,经常会遇到多个组件共享同一个状态,亦或是多个组件会去更新同一个状态,在应用代码量较少的时候,我们可以组件间通信去维护修改数据,或者是通过事件总线来进行数据的传递 ...

  10. Online Resource Mapping for SDN Network Hypervisors using Machine Learning

    发表时间:2016 一些定义: self-configuring networks: FlowVisor: FlowVisor是建立在OpenFlow之上的网络虚拟化工具,它可以将物理网络划分成多个逻 ...