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程序员技术职业生涯规划
看到很多PHP程序员职业规划的文章,都是直接上来就提Linux.PHP.MySQL.Nginx.Redis.Memcache.jQuery这些,然后就直接上手搭环境.做项目,中级就是学习各种PHP框架 ...
- Socket异步通信及心跳包同时响应逻辑分析(最后附Demo)。
有段时间没有更博了,刚好最近在做Socket通信的项目,原理大致内容:[二维码-(加logo)]-->提供主机地址和端口号信息(直接使用[ThoughtWorks.QRCode.dll]比较简单 ...
- Authorize的Forms认证
页面请求步骤: 1.登录地址: http://localhost:4441/SysLogin/AdminLogin 2.登陆成功地址:http://localhost:4441/Frame/MainF ...
- zookeeper 动态管理nginx配置
假设我们有一个场景,所有服务器共享同一份配置文件,我们肯定不可能单独手动维护每台服务器,这时可以利用zookeeper的配置管理功能. 环境:python + nginx + zookeeper 目的 ...
- ubuntu16.04在GTX1070环境下安装 cuda9.1
设备要求 系统:Ubuntu16.04 显卡:GTX 1070 驱动:nvidia系列,显卡驱动的版本必须大于等于cuda的sh文件名里面的版本号 驱动可从 此处 下载,我已经整理好了 检查安装驱动 ...
- Charles使用详解
前言: Charles是在 Mac 下常用的网络封包截取工具,在做移动开发时,我们为了调试与服务器端的网络通讯协议,常常需要截取网络封包来分析. 一.主界面介绍 二.网页抓包 启动 Cha ...
- C. Books Queries
链接 [http://codeforces.com/contest/1066/problem/C] 题意 开始空队列,可以进行前插和后插,还可以查询使某个数的为最左或最右需要去掉的最少数字 分析 模拟 ...
- 个人作业 Last
对M1/M2阶段的总结 M1阶段的总结反思见我以前的博客,我以前曾经写过.现附上链接.http://www.cnblogs.com/jirufeng/p/4990245.html M2阶段主要是对我们 ...
- C++高质量编程笔记
/* * 函数介绍: * 输入参数: * 输出参数: * 返回值 : */ void Function(float x, float y, float z) { - } if (-) { - whil ...
- elastic-search-kibana-in-docker-dotnet-core-app
[翻译] 使用ElasticSearch,Kibana,ASP.NET Core和Docker可视化数据 原文地址:http://www.dotnetcurry.com/aspnet/1354/e ...