链接: 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. Luogu4423 BJWC2011 最小三角形 平面最近点对

    传送门 题意:给出$N$个点,求其中周长最小的三角形(共线的也计算在内).$N \leq 2 \times 10^5$ 这道题唤起了我对平面最近点对的依稀记忆 考虑平面最近点对的分治,将分界线两边的求 ...

  2. 练习ng-show和ng-hide的方法

    在程序设计过程,我们需要把某一元素或是或一块进行显示与隐藏. 如你正使用angularjs的话,就可以使用ng-show或者ng-hide来进行控制. var showhideApp = angula ...

  3. Nginx URL后面不加斜杠301重定向

    今天开发碰到一个问题,其实之前就有这个问题,但是一直都没去关注,今天测试碰到了就解决一下. 问题情况: 当我请求 http://admindev.jingruiauto.com/store/views ...

  4. 2018 Multi-University Training Contest 2 部分简单题解析

    Preface 多校第二场,依靠罚时优势打到了校内的Rank 2 暴力分块碾标算系列 T4 Game 题目大意:在一个数集\([1,n]\)中两个人轮流选择其中的一个数,并从数集中删去这个数所有约数. ...

  5. SSL踩坑ERR_SSL_VERSION_OR_CIPHER_MISMATCH

    最近公司项目开发了一个微信小程序,并且部署测试OK,由于微信小程序调用的后端接口必须是HTTPS,所以给接口安装了SSL,第一天测试都正常.第二天早上再使用时页面无响应. 抓包发现是后端接口抛出: n ...

  6. eclipse取消空格、等号、分号自动录入

    默认eclipse中按空格.等号.分号等键时,会将提示框中的文字输入到编辑内容中,但是很多时候我们并不希望录入,可如下设置. 1.打开 Eclipse -> Window -> Perfe ...

  7. mysql下批量清空某个库下的所有表(库不要删除,保留空库)

    总所周知,mysql下要想删除某个库下的某张表,只需要切换到该库下,执行语句"drop table tablename"即可删除!但若是该库下有成百上千张表,要是再这样一次次执行d ...

  8. git 配置别名

    对于常用的git的命令,可以通过配置别名的方式,提高工作效率. $ git config --global alias.co checkout //执行git co 相当于git checkout $ ...

  9. 浅谈JS的作用域链(一)

    JS的执行环境 执行环境(Execution context,EC)或执行上下文,是JS中一个极为重要的概念. 在JavaScript中有三种代码运行环境: Global Code JavaScrip ...

  10. Codeforces Round #503 (by SIS, Div. 2)-C. Elections

    枚举每个获胜的可能的票数+按照花费排序 #include<iostream> #include<stdio.h> #include<string.h> #inclu ...