功能: 

修改与查询整个子树

修改与查询路径 可以时区间和  最大最小值  上同

求lca 

 


树链剖分 模板_最短路径树链剖分 模板_最短路径_02


#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
#define pb push_back
#define inf 0x3f3f3f3f
#define CLR(A,v) memset(A,v,sizeof A)
#define lson l,m,pos<<1
#define rson m+1,r,pos<<1|1
typedef pair<int,int>pii;
//////////////////////////////////
const int N=2e6+10;
const int M=1e6;

int t[N<<2],col[N<<2],w[N],n,mod,m,root,node[N];

void up(int pos)
{
t[pos]=t[pos<<1]+t[pos<<1|1];t[pos]%=mod;
}
void down(int m,int pos)
{
if(col[pos])
{
col[pos<<1]+=col[pos];
col[pos<<1|1]+=col[pos];
t[pos<<1]+=(m-(m>>1))*col[pos];t[pos<<1]%=mod;
t[pos<<1|1]+=(m>>1)*col[pos];t[pos<<1|1]%=mod;
col[pos]=0;
}
}
void build(int l,int r,int pos)
{
col[pos]=0;
if(l==r){t[pos]=w[l]%mod;return ;}//w为重新编号的权值
int m=(l+r)>>1;
build(lson);build(rson);
up(pos);
}
void update(int L,int R,int x,int l,int r,int pos)
{
if(L<=l&&r<=R)
{
t[pos]+=x*(r-l+1);t[pos]%=mod;col[pos]+=x;return ;
}
down(r-l+1,pos);
int m=(l+r)>>1;
if(L<=m)update(L,R,x,lson);
if(R>m)update(L,R,x,rson);
up(pos);
}
int query(int L,int R,int l,int r,int pos)
{
int ans=0;
if(L<=l&&r<=R)return t[pos];
down(r-l+1,pos);
int m=(l+r)>>1;
if(L<=m)ans+=query(L,R,lson),ans%=mod;
if(R>m)ans+=query(L,R,rson),ans%=mod;
up(pos);
return ans;
}
///////////////////////////////
int dep[N],siz[N],fa[N],son[N],head[M],pos,id[N],top[N],cnt;
struct Edge
{
int to,nex;
}edge[M];
void add(int a,int b)
{
edge[++pos].nex=head[a];
edge[pos].to=b;
head[a]=pos;
}
void dfs1(int x,int f,int deep)
{
dep[x]=deep;
fa[x]=f;
siz[x]=1;
int maxson=-1;
for(int i=head[x];i;i=edge[i].nex)
{
int v=edge[i].to;
if(v==f)continue;
dfs1(v,x,deep+1);
siz[x]+=siz[v];
if(siz[v]>maxson)maxson=siz[v],son[x]=v;
}
}
void dfs2(int x,int topf)
{
id[x]=++cnt;
w[cnt]=node[x];
top[x]=topf;
if(!son[x])return;
dfs2(son[x],topf);
for(int i=head[x];i;i=edge[i].nex)
{
int v=edge[i].to;
if(v==fa[x]||v==son[x])continue;
dfs2(v,v);
}
}
int qrange(int x,int y)//询问x到y最短路径的权值和
{
int ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans+=query(id[top[x]],id[x],1,n,1);
ans%=mod;
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
ans=(ans+query(id[x],id[y],1,n,1))%mod;
return ans;
}
void updaterange(int x,int y,int k)//将x 到y的最短路径上加k
{
k%=mod;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
update(id[top[x]],id[x],k,1,n,1);
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
update(id[x],id[y],k,1,n,1);
}
int qson(int x)//询问以x为根结点的子树去权值和
{
return query(id[x],id[x]+siz[x]-1,1,n,1);
}
void updateson(int x,int k)//将以x为根结点子树所有点的权值加k
{
update(id[x],id[x]+siz[x]-1,k,1,n,1);
}
int main()
{
cin>>n>>m>>root>>mod;
rep(i,1,n)RI(node[i]);
rep(i,1,n-1){int u,v;RII(u,v);add(u,v);add(v,u);}
dfs1(root,0,1);
dfs2(root,root);
build(1,n,1);
rep(i,1,m)
{
int k,x,y,z;RI(k);
if(k==1)
{
RIII(x,y,z);updaterange(x,y,z);
}
else if(k==2)
{
RII(x,y);printf("%d\n",qrange(x,y));
}
else if(k==3)
{
RII(x,y);updateson(x,y);
}
else
{
RI(x);printf("%d\n",qson(x));
}
}
return 0;
}

View Code

 

 


树链剖分 模板_最短路径树链剖分 模板_最短路径_02


int getlca(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}

LCA

 

大佬总结的非常好