链接: 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. 如何扩展32位EXE程序的使用内存

    1 运行Visual studio的命令行,执行下面命令:editbin /LARGEADDRESSAWARE “C:\Program Files\Skyline\TerraExplorer Pro\ ...

  2. React-使用react-redux

    react-redux可以方便在react中使用redux,我们就可以忘记subscribe,只需要记住reducer,action和dispatch就可以了.react-redux提供Provide ...

  3. 【转】Influxdb 编译

    编译针对当前 github上influxdb的master代码 其实github上的CONTRIBUTING.md 里已经说的很明白,按其一步步来开即开,唯一遇到的问题可能就是下载依赖时被墙无法下载, ...

  4. prop和attr的比较

    prop来获取或设置固有属性  removeProp()  删除固有属性 attr来获取或设置自定义属性     removeAttr() 删除自定义属性 案例:全选与全不选 <body> ...

  5. bitset常用用法&&简单题分析

    Preface bitset,还是一个比较好用的STL,可以给一些题目做到神奇的常数优化(\(O(\frac{原来的复杂度}{机器的位数(32位or64位)})\)) 关于一些具体的函数等内容可以参考 ...

  6. C#一些常用的图片操作方法:生成文字图片 合并图片等

    生成文字图片: /// <summary> /// 生成文字图片 /// </summary> /// <param name="text">& ...

  7. 20min 快速着手Markdown

    目录 Markdown介绍和基本使用 初步介绍 markdown的使用场景 为什么是 Markdown markdown的基本语法和使用平台 Q&A: Markdown介绍和基本使用 初步介绍 ...

  8. required: true,el-upload :action="UploadUrl()"

    <el-form-item label="所属班级:" prop="Name" :rules="[{ required: true, messa ...

  9. 小学四则运算APP 第一阶段冲刺

    需求分析 1.相关系统分析员向用户初步了解需求,然后用word列出要开发的系统的大功能模块,每个大功能模块有哪些小功能模块,对于有些需求比较明确相关的界面时,在这一步里面可以初步定义好少量的界面.[1 ...

  10. 二维数组转化为一维数组 contact 与apply 的结合

    将多维数组(尤其是二维数组)转化为一维数组是业务开发中的常用逻辑,除了使用朴素的循环转换以外,我们还可以利用Javascript的语言特性实现更为简洁优雅的转换.本文将从朴素的循环转换开始,逐一介绍三 ...