树链剖分就是划分轻重链,把每个点映射到线段树上,保证一条重链上的点在线段树中是一段完整的区间。可以由2遍dfs完成。主要还是个线段树。复杂度 O(nlogn+mlog2n) O ( n l o g n + m l o g 2 n )
树链剖分
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 30010
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,a[N],h[N],num=0,fa[N],dep[N],son[N],size[N],top[N],id[N],dfn=0;
struct edge{
int to,next;
}data[N<<1];
struct node{
int mx,sum;
}tree[N<<2];
void dfs1(int x){
size[x]=1;
for(int i=h[x];i;i=data[i].next){
int y=data[i].to;
if(fa[x]==y) continue;
fa[y]=x;dep[y]=dep[x]+1;dfs1(y);size[x]+=size[y];
if(size[y]>size[son[x]]) son[x]=y;
}
}
void dfs2(int x,int tp){
id[x]=++dfn;top[x]=tp;
if(son[x]) dfs2(son[x],tp);
for(int i=h[x];i;i=data[i].next){
int y=data[i].to;
if(y==fa[x]||y==son[x]) continue;
dfs2(y,y);
}
}
void build(int p,int l,int r){
if(l==r) return;
int mid=l+r>>1;
build(p<<1,l,mid);build(p<<1|1,mid+1,r);
}
inline void pushup(int p){
tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum;
tree[p].mx=max(tree[p<<1].mx,tree[p<<1|1].mx);
}
void change(int p,int l,int r,int x,int val){
if(l==r){tree[p].mx=tree[p].sum=val;return;}
int mid=l+r>>1;
if(x<=mid) change(p<<1,l,mid,x,val);
else change(p<<1|1,mid+1,r,x,val);
pushup(p);
}
int qsum(int p,int l,int r,int x,int y){
if(x<=l&&r<=y) return tree[p].sum;
int mid=l+r>>1,res=0;
if(x<=mid) res+=qsum(p<<1,l,mid,x,y);
if(y>mid) res+=qsum(p<<1|1,mid+1,r,x,y);
return res;
}
int qmax(int p,int l,int r,int x,int y){
if(x<=l&&r<=y) return tree[p].mx;
int mid=l+r>>1,res=-inf;
if(x<=mid) res=max(res,qmax(p<<1,l,mid,x,y));
if(y>mid) res=max(res,qmax(p<<1|1,mid+1,r,x,y));
return res;
}
int solvesum(int x,int y){
int res=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
res+=qsum(1,1,n,id[top[x]],id[x]);
x=fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
res+=qsum(1,1,n,id[x],id[y]);
return res;
}
int solvemax(int x,int y){
int res=-inf;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
res=max(res,qmax(1,1,n,id[top[x]],id[x]));
x=fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
res=max(res,qmax(1,1,n,id[x],id[y]));
return res;
}
int main(){
// freopen("a.in","r",stdin);
n=read();
for(int i=1;i<n;++i){
int x=read(),y=read();
data[++num].to=y;data[num].next=h[x];h[x]=num;
data[++num].to=x;data[num].next=h[y];h[y]=num;
}
dep[1]=1;dfs1(1);dfs2(1,1);build(1,1,n);
for(int i=1;i<=n;++i) change(1,1,n,id[i],read());int q=read();
while(q--){
char op[10];scanf("%s",op+1);int x=read(),y=read();
if(op[2]=='H') change(1,1,n,id[x],y);
if(op[2]=='S') printf("%d\n",solvesum(x,y));
if(op[2]=='M') printf("%d\n",solvemax(x,y));
}
return 0;
}
upd:也可以lct搞哟x
lct
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define inf 1000000000
#define ll long long
#define N 30010
int n,q,fa[N],c[N][2],stack[N],top=0,h[N],num=0;
ll sum[N],mx[N],w[N];
bool rev[N];
struct edge{
int to,next,val;
}data[N<<1];
inline int read(){
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline void dfs(int x){
for(int i=h[x];i;i=data[i].next){
int y=data[i].to;if(y==fa[x]) continue;
fa[y]=x;dfs(y);
}
}
inline bool isroot(int x){
return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;
}
inline void update(int x){
int l=c[x][0],r=c[x][1];
sum[x]=sum[l]+sum[r]+w[x];
mx[x]=max(mx[l],mx[r]);
mx[x]=max(mx[x],w[x]);
}
inline void pushdown(int x){
int l=c[x][0],r=c[x][1];
if(rev[x]){
rev[x]^=1;rev[l]^=1;rev[r]^=1;
swap(c[x][0],c[x][1]);
}
}
void rotate(int x){
int y=fa[x],z=fa[y];
bool t=(c[y][0]==x);
if(!isroot(y)) c[z][c[z][1]==y]=x;
fa[x]=z;fa[y]=x;fa[c[x][t]]=y;
c[y][t^1]=c[x][t];c[x][t]=y;
update(y);update(x);
}
void splay(int x){
stack[++top]=x;
for(int i=x;!isroot(i);i=fa[i]) stack[++top]=fa[i];
while(top) pushdown(stack[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if(c[y][1]==x^c[z][1]==y) rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x){
int y=0;
while(x){
splay(x);c[x][1]=y;update(x);y=x;x=fa[x];
}
}
void makeroot(int x){
access(x);splay(x);rev[x]^=1;
}
void link(int x,int y){
makeroot(x);fa[x]=y;
}
void split(int x,int y){
makeroot(x);access(y);splay(y);
}
int main(){
// freopen("a.in","r",stdin);
n=read();mx[0]=-inf;
for(int i=1;i<n;i++){
int x=read(),y=read();
data[++num].to=y;data[num].next=h[x];h[x]=num;
data[++num].to=x;data[num].next=h[y];h[y]=num;
}dfs(1);
for(int i=1;i<=n;i++) w[i]=mx[i]=sum[i]=read(),rev[i]=false;
q=read();
while(q--){
char op[10];int x,y;
scanf("%s",op);x=read(),y=read();
if(op[1]=='H'){
splay(x);
w[x]=y;
update(x);
}
if(op[1]=='S'){
split(x,y);printf("%lld\n",sum[y]);
}
if(op[1]=='M'){
split(x,y);printf("%lld\n",mx[y]);
}
}
return 0;
}