[模板]树链剖分

用途

我想把一个本来是线性的东西放到树上做,维护路径或者是子树的各种性质,那就用树剖呗

它可以套线段树、树状数组、ST表(以及其他我不知道的)

做法

我们考虑把树分成一条条链,然后对每条链维护我们的数据结构(线段树等)。对于两点间路径的询问,只要把路径拆成好几条链统计答案就可以了

然后为了保证链数是$O(logn)$的,我们需要把每个点和他的重儿子连成一条链,所谓重儿子,就是节点数最多的儿子

所以做两遍dfs,第一遍求出节点的重儿子、父节点和深度(用于统计答案),第二遍按照重儿子优先的顺序去做dfs序,这样可以保证每条重链连续、而且每个子树连续

我们以这个dfs序为下标,建一棵线段树(或者别的什么)

再记每个链的最靠上的节点是谁,然后查询的时候一直拿着个往上跳就行了

所以每次操作$O(log^2n)$

例题

luogu4114 Qtree1(修改边权、查询路径最大边权)

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<queue>
  6 #include<cmath>
  7 #include<ctime>
  8 #define LL long long int
  9 #define inf 0x3f3f3f3f
 10 using namespace std;
 11 const int maxn=100010;
 12 
 13 LL rd(){
 14    LL x=0;char c=getchar();int neg=1;
 15    while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
 16    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
 17    return x*neg;
 18 }
 19 
 20 struct Edge{
 21     int a,b,l,ne;
 22 }eg[maxn*2];
 23 int N;
 24 int egh[maxn],ect;
 25 int wson[maxn],fa[maxn],dep[maxn];
 26 int val[maxn],num[maxn],root[maxn],top[maxn],het[maxn];
 27 int ch[maxn*3][2],v[maxn*4],pct;
 28 
 29 inline void adeg(int a,int b,int l){
 30     eg[ect].a=a;eg[ect].b=b;eg[ect].l=l;eg[ect].ne=egh[a];egh[a]=ect++;
 31 }
 32 
 33 int dfs1(int x,int f){
 34     int ma=-inf,mi=0,re=1;fa[x]=f;dep[x]=dep[f]+1;
 35     for(int i=egh[x];i!=-1;i=eg[i].ne){
 36         int b=eg[i].b;if(b==f) continue;
 37         int c=dfs1(b,x);re+=c;
 38         val[b]=max(val[b],eg[i].l);
 39         if(c>ma) ma=c,mi=b;
 40     }wson[x]=mi;return re;
 41 }
 42 
 43 inline void update(int p){v[p]=max(v[ch[p][0]],v[ch[p][1]]);}
 44 
 45 void build(int &p,int l,int r){
 46     p=++pct;if(l==r) v[p]=val[num[l]];
 47     else{
 48         int m=l+r>>1;
 49         build(ch[p][0],l,m);build(ch[p][1],m+1,r);
 50         update(p);
 51     }
 52 }
 53 void change(int p,int l,int r,int x,int y){
 54     if(l==r) v[p]=y;
 55     else{
 56         int m=l+r>>1;
 57         if(x<=m) change(ch[p][0],l,m,x,y);
 58         else change(ch[p][1],m+1,r,x,y);
 59         update(p);
 60     }
 61 }
 62 int query(int p,int l,int r,int x,int y){
 63     if(x<=l&&r<=y) return v[p];
 64     else{
 65         int m=l+r>>1,re=-inf;
 66         if(x<=m) re=max(re,query(ch[p][0],l,m,x,y));
 67         if(y>=m+1) re=max(re,query(ch[p][1],m+1,r,x,y));
 68         return re;
 69     }
 70 }
 71 
 72 void dfs2(int x,int f){
 73     if(wson[f]!=x){int i,j;
 74         for(i=1,j=x;j;j=wson[j],i++) num[i]=j,top[j]=x;
 75         het[x]=i-1;build(root[x],1,het[x]);
 76     }for(int i=egh[x];i!=-1;i=eg[i].ne){
 77         int b=eg[i].b;if(b==f) continue;
 78         dfs2(b,x);
 79     }
 80 }
 81 
 82 void solveC(int a,int b){
 83     int x=eg[a*2-1].a,y=eg[a*2-1].b;
 84     if(dep[x]<dep[y]) swap(x,y);
 85     change(root[top[x]],1,het[top[x]],dep[x]-dep[top[x]]+1,b);
 86 }
 87 
 88 int solveQ(int x,int y){
 89     int re=-inf;if(x==y) return 0;
 90     while(top[x]!=top[y]){
 91         if(dep[top[x]]<dep[top[y]]) swap(x,y);
 92         re=max(re,query(root[top[x]],1,het[top[x]],1,dep[x]-dep[top[x]]+1));
 93         x=fa[top[x]];
 94     }if(x==y) return re;
 95     if(dep[x]>dep[y]) swap(x,y);
 96     return max(re,query(root[top[x]],1,het[top[x]],dep[x]-dep[top[x]]+2,dep[y]-dep[top[x]]+1));
 97 }
 98 
 99 int main(){
100     //freopen("4114.in","r",stdin);
101     int i,j,k;
102     char s[20];
103     N=rd();memset(egh,-1,sizeof(egh));
104     for(i=1;i<N;i++){
105         int a=rd(),b=rd(),c=rd();
106         adeg(a,b,c);adeg(b,a,c);
107     }dfs1(1,0);dfs2(1,0);
108     while(1){
109         scanf("%s",s);if(s[0]=='D') break;
110         i=rd(),j=rd();
111         if(s[0]=='C') solveC(i,j);
112         else printf("%d\n",solveQ(i,j));
113     }
114     return 0;
115 }
luogu4114

 suoi23 ZHX知识树 (改路径/子树点权 查路径/子树点权和/最大值)

  1 #include<bits/stdc++.h>
  2 #define pa pair<int,int>
  3 #define CLR(a,x) memset(a,x,sizeof(a))
  4 using namespace std;
  5 typedef long long ll;
  6 const int maxs=2e7,maxn=1e6+5,QS=233333333,QM=114514810;
  7 
  8 inline char gc(){
  9     static char buf[maxs],*p1=buf,*p2=buf;
 10     return p1==p2&&(p2=(p1=buf)+fread(buf,1,maxs,stdin),p1==p2)?EOF:*p1++;
 11 }
 12 
 13 inline ll rd(){
 14     ll x=0;char c=gc();int neg=1;
 15     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=gc();}
 16     while(c>='0'&&c<='9') x=x*10+c-'0',c=gc();
 17     return x*neg;
 18 }
 19 
 20 int eg[maxn*2][2],egh[maxn],ect;
 21 int N,M,root,fa[maxn];
 22 int dep[maxn],wson[maxn],dfn[maxn][2],top[maxn],siz[maxn];
 23 int ch[maxn*4][2],tot,id[maxn];
 24 int pct;
 25 ll sum[maxn*4],ma[maxn*4],laz[maxn*4];
 26 int v[maxn];
 27 
 28 inline void adeg(int a,int b){
 29     eg[++ect][0]=b;eg[ect][1]=egh[a];egh[a]=ect;
 30 }
 31 
 32 inline void update(int p){
 33     if(!ch[p][0]) return;
 34     sum[p]=sum[ch[p][0]]+sum[ch[p][1]];
 35     ma[p]=max(ma[ch[p][0]],ma[ch[p][1]]);
 36 }
 37 
 38 void build(int &p,int l,int r){
 39     if(!p) p=++pct;
 40     if(l==r) sum[p]=ma[p]=v[id[l]];
 41     else{
 42         int m=l+r>>1;
 43         build(ch[p][0],l,m);build(ch[p][1],m+1,r);
 44         update(p);
 45     }
 46 }
 47 
 48 inline void pushdown(int p,int l,int r){
 49     if(!laz[p]) return;
 50     if(l<r){
 51         int a=ch[p][0],b=ch[p][1];
 52         int m=l+r>>1;
 53         laz[a]+=laz[p];
 54         sum[a]+=(m-l+1)*laz[p];
 55         ma[a]+=laz[p];
 56         
 57         laz[b]+=laz[p];
 58         sum[b]+=(r-m)*laz[p];
 59         ma[b]+=laz[p];
 60     }laz[p]=0;
 61 }
 62 
 63 void add(int p,int l,int r,int x,int y,int z){
 64     if(x<=l&&r<=y){
 65         laz[p]+=z;
 66         sum[p]+=(r-l+1)*z;
 67         ma[p]+=z;
 68     }else{
 69         pushdown(p,l,r);
 70         int m=l+r>>1;
 71         if(x<=m) add(ch[p][0],l,m,x,y,z);
 72         if(y>=m+1) add(ch[p][1],m+1,r,x,y,z);
 73         update(p);
 74     }
 75 }
 76 
 77 ll querys(int p,int l,int r,int x,int y){
 78     pushdown(p,l,r);
 79     if(x<=l&&r<=y){
 80         return sum[p];
 81     }else{
 82         int m=l+r>>1;ll re=0;
 83         if(x<=m) re=querys(ch[p][0],l,m,x,y);
 84         if(y>=m+1) re+=querys(ch[p][1],m+1,r,x,y);
 85         return re;
 86     }
 87 }
 88 
 89 void querym(int p,int l,int r,int x,int y,ll &re){
 90     pushdown(p,l,r);
 91     if(x<=l&&r<=y){
 92         re=max(re,ma[p]);
 93     }else{
 94         int m=l+r>>1;
 95         if(x<=m&&ma[ch[p][0]]>re) querym(ch[p][0],l,m,x,y,re);
 96         if(y>=m+1&&ma[ch[p][1]]>re) querym(ch[p][1],m+1,r,x,y,re);
 97     }
 98 }
 99 
100 void dfs1(int x){
101     siz[x]=1;
102     int m=0;
103     for(int i=egh[x];i;i=eg[i][1]){
104         int b=eg[i][0];if(b==fa[x]) continue;
105         dep[b]=dep[x]+1;
106         fa[b]=x;
107         dfs1(b);
108         siz[x]+=siz[b];
109         if(siz[b]>m) m=siz[b],wson[x]=b;
110     }
111 }
112 
113 void dfs2(int x){
114     if(x==wson[fa[x]]) top[x]=top[fa[x]];
115     else top[x]=x;
116     dfn[x][0]=++tot;id[tot]=x;
117     if(wson[x]) dfs2(wson[x]);
118     for(int i=egh[x];i;i=eg[i][1]){
119         int b=eg[i][0];if(b==fa[x]||b==wson[x]) continue;
120         dfs2(b);
121     }
122     dfn[x][1]=tot;
123 }
124 
125 ll solve(int x,int y,int op){
126     ll re=(op==QM?-1e11:0);
127     while(top[x]!=top[y]){
128         if(dep[top[x]]<dep[top[y]]) swap(x,y);
129         if(op==QS){
130             re+=querys(root,1,N,dfn[top[x]][0],dfn[x][0]);
131         }else if(op==QM){
132             querym(root,1,N,dfn[top[x]][0],dfn[x][0],re);
133         }else{
134             add(root,1,N,dfn[top[x]][0],dfn[x][0],op);
135         }
136         x=fa[top[x]];
137     }if(dep[x]<dep[y]) swap(x,y);
138     if(op==QS){
139         re+=querys(root,1,N,dfn[y][0],dfn[x][0]);
140     }else if(op==QM){
141         querym(root,1,N,dfn[y][0],dfn[x][0],re);
142     }else{
143         add(root,1,N,dfn[y][0],dfn[x][0],op);
144     }
145     return re;
146 }
147 
148 int main(){
149     int i;
150     N=rd(),M=rd();
151     for(i=1;i<=N;i++) v[i]=rd();
152     for(i=1;i<N;i++){
153         int a=rd(),b=rd();
154         adeg(a,b);adeg(b,a);
155     }
156     dfs1(1);dfs2(1);
157     build(root,1,N);
158     for(i=1;i<=M;i++){
159         int op=rd(),x=rd();
160         if(op==1){
161             int y=rd(),v=rd();
162             solve(x,y,v);
163         }else if(op==2){
164             int v=rd();
165             add(root,1,N,dfn[x][0],dfn[x][1],v);
166         }else if(op==3){
167             printf("%lld\n",querys(root,1,N,dfn[x][0],dfn[x][0]));
168         }else if(op==4){
169             int y=rd();
170             printf("%lld\n",solve(x,y,QS));
171         }else if(op==5){
172             printf("%lld\n",querys(root,1,N,dfn[x][0],dfn[x][1]));
173         }else if(op==6){
174             int y=rd();
175             printf("%lld\n",solve(x,y,QM));
176         }else if(op==7){
177             ll re=-1e12;
178             querym(root,1,N,dfn[x][0],dfn[x][1],re);
179             printf("%lld\n",re);
180         }
181     }
182     return 0;
183 }
suoi23

 

转载于:https://www.cnblogs.com/Ressed/p/9404318.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/353155.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sql server 2005单独添加mdf文件

我把原来的数据库分离后&#xff0c;直接把日志文件给干掉了。原来在SQL 2000里经常这么干&#xff0c;只用一个mdf就附加了。没想到sql2005居然不行。我试验了一圈 终于找到一个成功的方法。转载&#xff0c;供后来者参考。SQL2005 如何在没有日志文件的情况下如何恢复MDF数据…

低压抽屉柜常见故障处理方法_低压配电设备常见故障分析,处理办法介绍

低压配电线路作为配电网络中主要的一部分&#xff0c;在其运行的过程中直接影响着人民的生命财产安全。配电线路是电力输送的终端&#xff0c;对于提高电力质量有着至关重要的作用。但由于配电线路走径的复杂性&#xff0c;人为因素和设备因素&#xff0c;都会给低压配电设备造…

关于C语言中的'\?'和%%

关于C语言中的\?和%% 一、引语 我们知道C/C中有四个非字母的字符需要用转义字符来表示&#xff1a;单引号 , 双引号 " , 反斜杆 \ 和问号 ? 显然这是因为它们本身有特殊的含义&#xff0c;所以要用转义字符来表示他们自己&#xff0c;单引号用来表示单个字符&#xff0…

mockito 使用_用Mockito回答

mockito 使用在编写单元测试时 &#xff0c;必须记住不要依赖于外部组件。 为了避免这种情况&#xff0c;我们使用了模拟框架&#xff0c;对我而言&#xff0c;最容易使用的是Mockito 。 在本文中&#xff0c;我们将看到在Mockito中使用的一种“高级”技术&#xff0c;可以使用…

jQuery常用操作

jQuery jQuery是一个轻量级的JS库&#xff0c;是一个被封装好的JS文件&#xff0c;提供了更为简便的元素操作方式&#xff0c;jQuery封装了DOM。 使用jQuery 引入jQuery文件 <scrtipt srcjquery-1.11.3.js> </script> 注意&#xff1a;引入必须放在其他jQuery操作之…

python tab和空格混用_我的 Python 编码规范

python 文件的组成为了便于描述&#xff0c;先上一个 demo#!/usr/bin/env python# -*- coding: utf-8 -*-"""通常这里是关于本文档的说明(docstring)&#xff0c;须以半角的句号、 问号或惊叹号结尾!本行之前应当空一行&#xff0c;继续完成关于本文档的说明如果…

Twitter创始人Jack Dorsey的每日必做和不做清单

Twitter创始人Jack Dorsey显然是这段时间以来技术界的中心人物&#xff0c;不仅发表了一系列的文章&#xff0c;而且一本反映Twitter早期岁月的书也即将出版。今天&#xff0c;他又在Y Combinator的Startup School上发表了讲话&#xff0c;不过在谈话中Dorsey回避了一切不必要及…

JSR-308和Checker框架为jOOQ 3.9添加了更多类型安全性

Java 8引入了JSR-308&#xff0c;它为Java语言添加了新的注释功能。 最重要的是&#xff1a;键入注释。 现在可以像下面这样设计怪物了&#xff1a; 比注解更疯狂的是类型注解。 在数组上。 谁认为这是有效的Java代码&#xff1f; pic.twitter.com/M9fSRRerAD — Lukas Eder&…

Linux NTP服务配置 for Oracle RAC

安装Oracle 11g RAC时&#xff0c;我们需要配置ntp服务。在使用虚拟机的情况下对于时钟同步方式的配置有很多种方式&#xff0c;可以使用vmware自带的时钟同步功能&#xff0c;也可以直接将本地的一个节点用作时间服务器。本文介绍直接配置ntp方式的时钟服务器。1、查看两节点的…

java字符编码方式总结

java字符编码方式总结一、概要在JAVA应用程序特别是基于WEB的程序中&#xff0c;经常遇到字符的编码问题。为了防止出现乱码&#xff0c;首先需要了解JAVA是如何处理字符的&#xff0c;这样就可以有目的地在输入/输出环节中增加必要的转码。其次&#xff0c;由于各种服务器有不…

按键扫描

unsigned char Trg,cont,num;void key_sm(void) { uchar Read;ReadP0^0xff;TrgRead&(Read^cont);contRead; } void key_hs(){  switch(Trg)   {     case 0x01:       num;     break;     case 0x02:       num--;     break;     d…

Mathematica函数大全

一、运算符及特殊符号 Line1; 执行Line&#xff0c;不显示结果 Line1,line2 顺次执行Line1&#xff0c;2&#xff0c;并显示结果 ?name 关于系统变量name 的信息 ??name 关于系统变量name 的全部信息 !command 执行Dos 命令 n! N 的阶乘 !!filename 显示文件内容 <<fi…

oem是代工还是贴牌_食用油OEM贴牌代工业务要注意哪些问题?

近年来食用油OEM业务逐渐增加&#xff0c;OEM是英文 Original Equipment Manufacturer的缩写&#xff0c;被译为代工生产或贴牌生产&#xff0c;通常是指品牌商委托有生产能力且品质有保证的油脂加工厂来生产食用油产品&#xff0c;对自己及对方的品牌不会有冲突&#xff0c;且…

java 简化判断_简化Java内存分析

java 简化判断作为一名典型的Java开发人员&#xff0c;除了遵循关闭连接&#xff0c;流等典型的最佳实践外&#xff0c;我从未监视过应用程序的内存使用情况。最近&#xff0c;我们在JBoss服务器中遇到了一些问题&#xff0c;不得不深入研究内存管理Java中最好的事情之一是&…

DRF的序列化组件

rest rest下的url url唯一代表资源&#xff0c;http请求方式来区分用户行为 url的设计规范 GET&#xff1a; 127.0.0.1:9001/books/       # 获取所有数据 GET: 127.0.0.1:9001/books/{id}      # 获取单条数据 POST&#xff1a; 127.0.0.1:9001/books/      # 增…

15crmo焊接后多长时间探伤_承压设备渗透探伤检测方法简单操作思路

啥是渗透检测渗透检测俗称渗透探伤&#xff0c;是一种以毛细管作用原理为基础用于检查表面开口缺陷的无损检测方法。它与射线检测、超声检测、磁粉检测和涡流检测一起&#xff0c;并称为5种常规的无损检测方法&#xff0c;渗透检测始于本世纪初&#xff0c;是目视检查以外最早应…

SpringBoot实战(五)之Thymeleaf

Thymeleaf同jsp、volocity、freemarker等共同的职能是MVC模式中的视图展示层&#xff0c;即View。 当然了&#xff0c;SpringBoot中也可以用jsp,不过不推荐这种用法&#xff0c;比较推崇的就是使用Thymeleaf。 关于Thymeleaf学习&#xff0c;建议参考官方文档:https://www.thym…

Arrays.sort()

今天在做一个按更新时间搜寻出某个文件夹里面的所有文件&#xff0c;由于自己写算法比较花费时间&#xff0c;干脆就用j2se提供的类Arrays提供的sort&#xff08;&#xff09;方法&#xff0c;这样就比较省力。对于基本数据类型只要Arrays.sort(数组)[“注&#xff1a;数组是声…

Thymeleaf 3 – Thymeleaf 3和Spring MVC快速入门

Thymeleaf 3发布到达。 新版本带来了许多新功能&#xff0c;例如HTML5支持以及不带标记的文本模板支持– [# th:utext"${thymeleaf.version}" /] &#xff0c;改进的内联功能– <p>Thymeleaf [[${thymeleaf.version}]] is great!</p> &#xff0c;性能改…