#include <iostream>
#include <vector>
using namespace std;
const int maxn=(int)1e5+5;
int n,q;
vector<int>G[maxn];
/*---树链剖分---*/
int fa[maxn],son[maxn],sz[maxn],deep[maxn];
void dfs1(int p,int u,int d){
deep[u]=d;fa[u]=p;sz[u]=1;
for(auto v:G[u]){
if(v==fa[u])continue;
dfs1(u,v,d+1);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]])son[u]=v;
}
}
int id[maxn],mark[maxn],top[maxn],cnt;
void dfs2(int t,int u){
id[u]=++cnt;mark[cnt]=u;
top[u]=t;
if(son[u])dfs2(t,son[u]);
for(auto v:G[u]){
if(v==fa[u])continue;
if(v==son[u])continue;
dfs2(v,v);
}
}
/*---树链剖分---*/
/*---线段树---*/
#define lson rt<<1
#define rson rt<<1|1
int sum[maxn<<2],lazy[maxn<<2];
//如果需要建树
void build(){}
void pushdown(int rt,int l,int r){
if(lazy[rt]){
lazy[lson]+=lazy[rt];
lazy[rson]+=lazy[rt];
sum[lson]+=lazy[rt]*l;
sum[rson]+=lazy[rt]*r;
lazy[rt]=0;
}
}
void pushup(int rt){
sum[rt]=sum[lson]+sum[rson];
}
void update(int rt,int x,int l,int r,int L,int R){
if(l<=L && r>=R){
lazy[rt]+=x;
sum[rt]+=(R-L+1)*x;
return;
}
int mid=(L+R)>>1;
pushdown(rt,mid-L+1,R-mid);
if(r<=mid)update(lson,x,l,r,L,mid);
else if(l>mid)update(rson,x,l,r,mid+1,R);
else update(lson,x,l,mid,L,mid),update(rson,x,mid+1,r,mid+1,R);
pushup(rt);
};
int query(int rt,int l,int r,int L,int R){
if(l<=L && r>=R) return sum[rt];
int mid=(L+R)>>1;
pushdown(rt,mid-L+1,R-mid);
if(r<=mid) return query(lson,l,r,L,mid);
else if(l>mid) return query(rson,l,r,mid+1,R);
else return query(lson,l,mid,L,mid)+query(rson,mid+1,r,mid+1,R);
}
/*---线段树---*/
/*---树链+线段树---*/
void change(int a,int b,int x){
while(top[a]!=top[b]){
//使 b 的 top 的深度大
if(deep[top[a]]>deep[top[b]])swap(a,b);
int tb=top[b];
int s=id[tb],e=id[b];
update(1,x,s,e,1,n);
b=fa[tb];
}
if(id[a]>id[b])swap(a,b);
update(1,x,id[a],id[b],1,n);
}
int ask(int a,int b){
int ans=0;
while(top[a]!=top[b]){
if(deep[top[a]]>deep[top[b]])swap(a,b);
int tb=top[b];
int s=id[tb],e=id[b];
ans+=query(1,s,e,1,n);
b=fa[tb];
}
if(id[a]>id[b])swap(a,b);
ans+=query(1,id[a],id[b],1,n);
return ans;
}
/*---树链+线段树---*/
int main(){
ios::sync_with_stdio(false);
cin>>n>>q;
for(int i=1,u,v;i<n;i++){
cin>>u>>v;
G[u].push_back(v);
G[v].push_back(u);
}
dfs1(0,1,1);
dfs2(1,1);
while(q--){
int a,b,c,d;
cin>>a>>b>>c>>d;
change(a,b,1);
cout<<ask(c,d)<<endl;
change(a,b,-1);
}
return 0;
}
树链剖分-重链剖分模板
最新推荐文章于 2024-03-24 17:40:24 发布