博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【loj#139】树链剖分
阅读量:5153 次
发布时间:2019-06-13

本文共 3995 字,大约阅读时间需要 13 分钟。

#139. 树链剖分

 
题目描述

这是一道模板题。

给定一棵 $n$个节点的树,初始时该树的根为 111 号节点,每个节点有一个给定的权值。下面依次进行 $m$ 个操作,操作分为如下五种类型:

  • 换根:将一个指定的节点设置为树的新根。

  • 修改路径权值:给定两个节点,将这两个节点间路径上的所有节点权值(含这两个节点)增加一个给定的值。

  • 修改子树权值:给定一个节点,将以该节点为根的子树内的所有节点权值增加一个给定的值。

  • 询问路径:询问某条路径上节点的权值和。

  • 询问子树:询问某个子树内节点的权值和

输入格式

第一行为一个整数 n,表示节点的个数。

第二行 n 个整数表示第 iii 个节点的初始权值 $a_i$​。

第三行 n−1 个整数,表示 i+1i+1i+1 号节点的父节点编号$ fi+1 (1⩽fi+1⩽n)f_{i+1}\ (1 \leqslant f_{i+1} \leqslant n)fi+1​ (1⩽fi+1​⩽n)。$

第四行一个整数 m,表示操作个数。

接下来 m 行,每行第一个整数表示操作类型编号:$(1⩽u,v⩽n)(1 \leqslant u, v \leqslant n)(1⩽u,v⩽n)$

  • 若类型为 111,则接下来一个整数 u,表示新根的编号。

  • 若类型为 222,则接下来三个整数 u,v,ku,v,ku,v,k,分别表示路径两端的节点编号以及增加的权值。

  • 若类型为 333,则接下来两个整数 u,ku,ku,k,分别表示子树根节点编号以及增加的权值。

  • 若类型为 444,则接下来两个整数 u,vu,vu,v,表示路径两端的节点编号。

  • 若类型为 555,则接下来一个整数 u,表示子树根节点编号。

输出格式

对于每一个类型为 444 或 555 的操作,输出一行一个整数表示答案。

样例
样例输入
61 2 3 4 5 61 2 1 4 464 5 62 2 4 15 11 43 1 24 2 5
样例输出
152419
数据范围与提示

对于 $100%100\%100%$ 的数据,$1⩽n,m,k,ai⩽1051\leqslant n,m,k,a_i\leqslant 10^51⩽n,m,k,ai​⩽105$。数据有一定梯度。

 

题意:树链加,子树加,需要支持换根,查询树链和,子树和

题解:

        树链剖分模板,树链加和查询直接树链剖分即可,

        注意到树链剖分有个很方便的性质就是链剖的序列其实也是dfs序,记录一个点的序列上起点和终点就可以顺便维护子树,

       换根的话分类讨论一下,一直以1号点为根,对树链的修查无影响,考虑子树:

         假设访问u号点,在以1号点为根的形态下:

         当前根rt,如果u==rt则u的子树为整个以1为根的树,

         如果rt是u的子树里的节点,那么u所代表的的子树就是整个子树 - rt的祖先里u的儿子的  子树 ,

         如果rt不是u的子树里的节点,那么u的子树就是以1为根时u的子树;

         这样操作后也是区间,可以和前两个一起维护;

      

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #define ls (k<<1) 11 #define rs (k<<1|1) 12 #define Run(i,l,r) for(int i=l;i<=r;i++) 13 #define Don(i,l,r) for(int i=l;i>=r;i--) 14 #define ll long long 15 #define inf 0x3f3f3f3f 16 using namespace std; 17 const int N=100010; 18 int n,m,o,hd[N],tp[N],st[N],ed[N],idx,son[N],fa[N],w[N],sz[N],dep[N],root;// 19 ll val[N],sum[N<<2],ly[N<<2];// 20 struct Edge{ int v,nt;}E[N<<1]; // 21 char gc(){ 22 static char*p1,*p2,s[1000000]; 23 if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin); 24 return(p1==p2)?EOF:*p1++; 25 }// 26 int rd(){ 27 int x=0,f=1; char c=gc(); 28 while(c<'0'||c>'9'){ if(c=='-')f=-1;c=gc();} 29 while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0',c=gc();} 30 return x*f; 31 }// 32 void adde(int u,int v){ 33 E[o]=(Edge){v,hd[u]};hd[u]=o++; 34 E[o]=(Edge){u,hd[v]};hd[v]=o++; 35 }// 36 void dfsA(int u,int F){ 37 dep[u]=dep[F]+1; 38 son[u]=0; sz[u]=1; 39 for(int i=hd[u];~i;i=E[i].nt){ 40 int v=E[i].v; 41 if(v==F)continue; 42 dfsA(v,u); 43 sz[u]+=sz[v]; 44 if(sz[v]>sz[son[u]])son[u]=v; 45 } 46 }// 47 void dfsB(int u,int T){ 48 tp[u]=T; val[st[u]=++idx]=w[u]; 49 if(son[u])dfsB(son[u],T); 50 for(int i=hd[u];~i;i=E[i].nt){ 51 int v=E[i].v; 52 if(v==son[u]||v==fa[u])continue; 53 dfsB(v,v); 54 } 55 ed[u]=idx; 56 }// 57 void pushup(int k){sum[k]=sum[ls]+sum[rs];}// 58 void mfy(int k,int l,int r,ll v){sum[k]+=v*(r-l+1);ly[k]+=v;}// 59 void pushdown(int k,int l,int r){ 60 if(ly[k]){ 61 int mid=(l+r)>>1; 62 mfy(ls,l,mid,ly[k]); 63 mfy(rs,mid+1,r,ly[k]); 64 ly[k]=0; 65 } 66 }// 67 void build(int k,int l,int r){ 68 if(l==r){sum[k]=val[l];ly[k]=0;return;} 69 int mid=(l+r)>>1; 70 build(ls,l,mid); 71 build(rs,mid+1,r); 72 pushup(k); 73 }// 74 void update(int k,int l,int r,int x,int y,ll v){ 75 if(l==x&&r==y)mfy(k,l,r,v); 76 else { 77 pushdown(k,l,r); 78 int mid=(l+r)>>1; 79 if(y<=mid)update(ls,l,mid,x,y,v); 80 else if(x>mid)update(rs,mid+1,r,x,y,v); 81 else update(ls,l,mid,x,mid,v) , update(rs,mid+1,r,mid+1,y,v); 82 pushup(k); 83 } 84 }// 85 ll query(int k,int l,int r,int x,int y){ 86 if(l==x&&r==y)return sum[k]; 87 else { 88 pushdown(k,l,r); 89 int mid=(l+r)>>1; 90 if(y<=mid)return query(ls,l,mid,x,y); 91 else if(x>mid)return query(rs,mid+1,r,x,y); 92 else return query(ls,l,mid,x,mid) + query(rs,mid+1,r,mid+1,y); 93 } 94 }// 95 int child(int u,int v){ 96 while(tp[u]!=tp[v]){ 97 u=tp[u]; 98 if(fa[u]==v)return u; 99 u=fa[u];100 }101 return son[v];102 }//103 void update1(int u,int v,int x){104 while(tp[u]!=tp[v]){105 if(dep[tp[u]]
View Code

 

转载于:https://www.cnblogs.com/Paul-Guderian/p/9814325.html

你可能感兴趣的文章
解决Ubuntu下博通网卡驱动问题
查看>>
Oracle中的instead of触发器
查看>>
【bzoj2788】Festival
查看>>
执行gem install dryrun错误
查看>>
Java SE之正则表达式一:概述
查看>>
HTML5简单入门系列(四)
查看>>
实现字符串反转
查看>>
转载:《TypeScript 中文入门教程》 5、命名空间和模块
查看>>
苹果开发中常用英语单词
查看>>
[USACO 1.4.3]等差数列
查看>>
Shader Overview
查看>>
Reveal 配置与使用
查看>>
Java中反射的学习与理解(一)
查看>>
nginx配置socket服务
查看>>
C语言初学 俩数相除问题
查看>>
B/S和C/S架构的区别
查看>>
[Java] Java record
查看>>
jQuery - 控制元素显示、隐藏、切换、滑动的方法
查看>>
postgresql学习文档
查看>>
Struts2返回JSON数据的具体应用范例
查看>>