hdu 6394 Tree (2018 Multi-University Training Contest 7 1009) (树分块+倍增)
链接: 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) (树分块+倍增)的更多相关文章
- HDU 6395 2018 Multi-University Training Contest 7 (快速幂+分块)
原题地址 Sequence Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)T ...
- 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 ...
- HDU 6143 - Killer Names | 2017 Multi-University Training Contest 8
/* HDU 6143 - Killer Names [ DP ] | 2017 Multi-University Training Contest 8 题意: m个字母组成两个长为n的序列,两序列中 ...
- HDU 6074 - Phone Call | 2017 Multi-University Training Contest 4
看标程的代码这么短,看我的.... 难道是静态LCA模板太长了? /* HDU 6074 - Phone Call [ LCA,并查集 ] | 2017 Multi-University Traini ...
- HDU 6068 - Classic Quotation | 2017 Multi-University Training Contest 4
/* HDU 6068 - Classic Quotation [ KMP,DP ] | 2017 Multi-University Training Contest 4 题意: 给出两个字符串 S[ ...
- HDU 6076 - Security Check | 2017 Multi-University Training Contest 4
/* HDU 6076 - Security Check [ DP,二分 ] | 2017 Multi-University Training Contest 4 题意: 给出两个检票序列 A[N], ...
- HDU 6071 - Lazy Running | 2017 Multi-University Training Contest 4
/* HDU 6071 - Lazy Running [ 建模,最短路 ] | 2017 Multi-University Training Contest 4 题意: 四个点的环,给定相邻两点距离, ...
- 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] 要求满 ...
- HDU 6070 - Dirt Ratio | 2017 Multi-University Training Contest 4
比赛时会错题意+不知道怎么线段树维护分数- - 思路来自题解 /* HDU 6070 - Dirt Ratio [ 二分,线段树 ] | 2017 Multi-University Training ...
- HDU 6036 - Division Game | 2017 Multi-University Training Contest 1
/* HDU 6036 - Division Game [ 组合数学,NTT ] | 2017 Multi-University Training Contest 1 题意: k堆石子围成一个圈,数量 ...
随机推荐
- php和js字符串的acsii码函数
简单普及下编码知识: javascript中有charCodeAt(),根据字符查找ascii码. String.fromCharCode(),根据ascii码查找对应的字符. console.log ...
- ssl协议
在互联网安全通信方式上,目前用的最多的就是https配合ssl和数字证书来保证传输和认证安全了.本文追本溯源围绕这个模式谈一谈. 1.首先解释一下上面的几个名词: https:在http(超文本传输协 ...
- P5204 [USACO19JAN]Train Tracking 2
P5204 [USACO19JAN]Train Tracking 2 毒毒题,对着嘤文题解看了贼久 首先考虑此题的一个弱化版本:如果输入的所有\(c_i\)相等怎么做 现在假设有\(len\)个数,取 ...
- GATT服务搜索流程(一)
GATT的规范阅读起来还是比较简答, 但是这样的规范在代码上是如何实现的呢?下面就分析一下bluedroid 协议栈关于GATT的代码流程. BLE的设备都是在SMP之后进行ATT的流程的交互.从代码 ...
- C# 爬虫 正则、NSoup、HtmlAgilityPack、Jumony四种方式抓取小说
心血来潮,想爬点小说.通过百度选择了个小说网站,随便找了一本小说http://www.23us.so/files/article/html/13/13655/index.html. 1.分析html规 ...
- Centos6.9下RabbitMQ集群部署记录
之前简单介绍了CentOS下单机部署RabbltMQ环境的操作记录,下面详细说下RabbitMQ集群知识,RabbitMQ是用erlang开发的,集群非常方便,因为erlang天生就是一门分布式语言, ...
- Linux下DNS简单部署(主从域名服务器)
一.DNS简介DNS(Domain Name System),域名系统,因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串.通 ...
- Redis常用操作-------Set(集合)
1.SADD key member [member ...] 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略. 假如 key 不存在,则创建一个 ...
- Liinux 学习心得
Linux 内核学习心得 姬梦馨 原创作品 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 反汇编一个简 ...
- 猜字游戏java
一.实践目的 1.掌握基本输入输出. 2.掌握方法定义与调用,理解参数传递方式. 3.掌握数组的声明.定义与初始化,数组的处理. 4.掌握数组作为方法参数和返回值. 二.实践要求 利用方法.数组.基本 ...