树链剖分
看了http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html学习了树链剖分
适用于在树上的路径操作。
关键在于重链的构造,把它表示到了数据结构上的连续区间,降低了复杂度。
主要操作步骤实际上有三个部分
1: 构造重链
2: 如何维护数据
3: 分解为轻重链的查询与修改
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#define N 10010
using namespace std;
struct node{
int e,next,w;
}K[N*2];
int now;
int num;
int son[N],_hash[N],deep[N],head[N],fa[N],sum[N],top[N];
void add(int x,int y,int w){
K[now].e=y;
K[now].w=w;
K[now].next=head[x];
head[x]=now++;
return ;
}
int dfs(int x,int f){
fa[x]=f;
son[x]=0,sum[x]=1;
for(int i=head[x];~i;i=K[i].next){
int to=K[i].e;
if(to==f)continue;
deep[to]=deep[x]+1;
dfs(to,x);
sum[x]+=sum[to];
if(sum[to]>sum[son[x]]||son[x]==0)son[x]=to; //重子的选择
}
return ;
}
void build_tree(int x,int f){
_hash[x]=num++; //映射结点到线段树上
top[x]=f; //重链端点
if(son[x]!=0)build_tree(son[x],f);
for(int i=head[x];~i;i=K[i].next){
int to=K[i].e;
if(son[x]!=to)build_tree(to,to);
}
return ;
}
void modify(int x,int y,int z){
<span style="white-space:pre"> </span>while(top[x]!=top[y]){
//printf("f1=%d,f2=%d\n",f1,f2);
if(deep[top[x]]<deep[top[y]])swap(x,y);
l=_hash[x],r=_hash[top[x]];//r<l
<span style="white-space:pre"> </span>//修改r,l
x=fa[top[x]];
}
l=_hash[x],r=_hash[y];
if(l>r)swap(l,r);
//修改l,r
}