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

题意

给出一棵树,然后每个节点有一个权值,代表这个点可以往上面跳多远,问最少需要多少次可以跳出这颗树

分析

先dfs一次得到dfs序,然后按dfs序分块。倍增计算从某点跳x到哪个点,用cn保存它跳出这一块需要的次数,ne保存跳出这块会去的点。然后块内就暴力修改了。复杂度nsqrt(n);

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(a, b) memset(a, b, sizeof(a))
#define pb push_back
#define mp make_pair
#define pii pair<int, int>
#define eps 0.0000000001
#define IOS ios::sync_with_stdio(0);cin.tie(0);
#define random(a, b) rand()*rand()%(b-a+1)+a
#define pi acos(-1)
const ll INF = 0x3f3f3f3f3f3f3f3fll;
const int inf = 0x3f3f3f3f;
const int maxn = 1e5 + ;
const int maxm = + ;
const int mod = ; int w[maxn],fa[][maxn],n,m;
int head[maxn],nxt[maxn],to[maxn],tot;
int id[maxn],cnt;//dfs序
int num,block,belong[maxn],l[maxn],r[maxn];//块的数目,快的大小,属于那块,每块的左右边界
int cn[maxn],ne[maxn],pre[maxn];//跳出本块的次数,跳向的下一块的点,这个点会跳向的位置 void init(){
memset(head,-,sizeof(head));
cnt=tot=;
}
void addedge(int u,int v){
to[tot]=v;
nxt[tot]=head[u];
head[u]=tot++;
}
void dfs1(int u,int f){//dfs一次,得到dfs序和每一个点的父亲
fa[][u]=f;
id[u]=++cnt;
for(int i=head[u];~i;i=nxt[i]){
dfs1(to[i],u);
}
}
void build(){//分块
block=sqrt(n);
num=(n+block-)/block;
for(int i=;i<=n;i++){
belong[i]=(i-)/block+;
}
for(int i=;i<=num;i++){
l[i]=(i-)*block+;
r[i]=i*block;
}
r[num]=n;
}
int find(int u,int l){
for(int i=;i>=;i--){
if((l>>i)&){
u=fa[i][u];
}
}
return u;
}
void dfs2(int u){//再次dfs得到cn[N],net[N],pre[N]
int f=find(u,w[u]);
pre[id[u]]=id[f];
if(id[f]<l[belong[id[u]]]) cn[id[u]]=,ne[id[u]]=id[f];
else cn[id[u]]=cn[id[f]]+,ne[id[u]]=ne[id[f]];
for(int i=head[u];~i;i=nxt[i]){
dfs2(to[i]);
}
}
int query(int u){
int ans=;
while(u>){
ans+=cn[u];
u=ne[u];
}
return ans;
}
void update(int u,int val){
int f=find(u,val);
w[u]=val;
pre[id[u]]=id[f];
if(id[f]<l[belong[id[u]]]) cn[id[u]]=,ne[id[u]]=id[f];
else cn[id[u]]=cn[id[f]]+,ne[id[u]]=ne[id[f]];
for(int i=id[u]+;i<=r[belong[id[u]]];i++){//更新这块内后面的点
if(pre[i]>=l[belong[i]]){
cn[i]=cn[pre[i]]+;
ne[i]=ne[pre[i]];
}
}
}
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
int T;
scanf("%d",&T);
while(T--){
init();
scanf("%d",&n);
for(int i=;i<=n;i++){
int x;
scanf("%d",&x);
addedge(x,i);
}
for(int i=;i<=n;i++){
scanf("%d",&w[i]);
}
dfs1(,);
for(int i=;i<;i++){
for(int j=;j<=n;j++){
fa[i][j]=fa[i-][fa[i-][j]];
}
}
build();
dfs2();
scanf("%d",&m);
while(m--){
int op,x,y;
scanf("%d%d",&op,&x);
if(op==){
printf("%d\n",query(id[x]));
}else{
scanf("%d",&y);
update(x,y);
}
}
}
return ;
}

HDU - 6394 Tree(树分块+倍增)的更多相关文章

  1. hdu 6394 Tree (2018 Multi-University Training Contest 7 1009) (树分块+倍增)

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=6394 思路:用dfs序处理下树,在用分块,我们只需要维护当前这个点要跳出这个块需要的步数和他跳出这个块去 ...

  2. HDU 6394 Tree 分块 || lct

    Tree 题意: 给你一颗树, 每一个节点都有一个权值, 如果一个石头落在某个节点上, 他就会往上跳这个的点的权值步. 现在有2种操作, 1 把一个石头放在 x 的位置 询问有跳几次才跳出这棵树, 2 ...

  3. HDU 5044 Tree 树链剖分+区间标记

    Tree Problem Description You are given a tree (an acyclic undirected connected graph) with N nodes. ...

  4. HDU 5044 Tree --树链剖分

    题意:给一棵树,两种操作: ADD1: 给u-v路径上所有点加上值k, ADD2:给u-v路径上所有边加上k,初始值都为0,问最后每个点和每条边的值,输出. 解法:树链剖分可做,剖出来如果直接用线段树 ...

  5. hdu 4366 Successor - CDQ分治 - 线段树 - 树分块

    Sean owns a company and he is the BOSS.The other Staff has one Superior.every staff has a loyalty an ...

  6. Hdu 5274 Dylans loves tree (树链剖分模板)

    Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...

  7. HDU 5044 Tree(树链剖分)

    HDU 5044 Tree field=problem&key=2014+ACM%2FICPC+Asia+Regional+Shanghai+Online&source=1&s ...

  8. [HDU 5293]Tree chain problem(树形dp+树链剖分)

    [HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...

  9. 洛谷 P6177 - Count on a tree II/【模板】树分块(树分块)

    洛谷题面传送门 好家伙,在做这道题之前我甚至不知道有个东西叫树分块 树分块,说白了就是像对序列分块一样设一个阈值 \(B\),然后在树上随机撒 \(\dfrac{n}{B}\) 个关键点,满足任意一个 ...

随机推荐

  1. quartus prime 16.0 报警告 inferring latch

    前言 当写always组合逻辑块时,可能会写出 poor code.综合时软件会推断出锁存器.例如下面代码: always @* begin 'b1) begin w = (a & b) ^ ...

  2. MT【312】特征根法求数列通项

    (2016清华自招领军计划37题改编) 设数列$\{a_n\}$满足$a_1=5,a_2=13,a_{n+2}=\dfrac{a^2_{n+1}+6^n}{a_n}$则下面不正确的是(      )A ...

  3. MS-DOS 6.22 +Vim+masm 汇编环境

    安装vim 个人习惯用 vim 编辑,因此稍微折腾了一下.不用这么麻烦直接用 edit 编辑也是可以的. 原来安装的 MS-DOS 7.10 虚拟机安装好vim后无法运行,所以改用了 MS-DOS 6 ...

  4. Android自带Monkey测试

    Monkey是在模拟器上或设备上运行的一个小程序,它能够产生为随机的用户事件流,例如点击(click),触摸(touch),挥手(gestures),还有一系列的系统级事件.可以使用Monkey来给正 ...

  5. Spring -- <mvc:annotation-driven />

    <mvc:annotation-driven /> 会自动注册:RequestMappingHandlerMapping .RequestMappingHandlerAdapter 与Ex ...

  6. 洛谷P2150 寿司晚宴

    解:发现每个质数只能属于一个人,于是想到每个质数有三种情况:属于a,属于b,都不属于. 然后考虑状压每个人的质数集合,可以得到30分. 转移就是外层枚举每个数,内层枚举每个人的状态,然后看能否转移.能 ...

  7. 【CH6803】导弹防御塔

    题目大意:给定 N 座塔,M 个怪物,每座塔一次可以发射一枚导弹,发射导弹有发射时间和冷却时间,每座塔和每只怪物有自己的二维坐标,所有导弹有一个共同的速度,求至少需要多长时间才能将所有怪物消灭. 题解 ...

  8. React之Perf

    import Perf from 'react-addons-perf' // ES6语法 var Perf = require('react-addons-perf') // ES5语法针对node ...

  9. 第十七篇-使用RadioGroup实现单项选择

    上效果图 首先进行控件布局,一个textview,6个radiobutton, main_activity.xml <?xml version="1.0" encoding= ...

  10. Python基础-元组、列表、字典

    元组tuple 元组被称为只读列表,即数据可以被查询,但不能被修改,所以,字符串的切片操作同样适用于元组.例:(1,2,3)("a","b","c&q ...