树上差分
树上差分
顾名思义,就是对树上路径或子树和整体加减时可以利用树上差分。
当然也可以线段树维护(树链剖分)
例如,要让x到y的这段路径上所以节点加1
就让我们差分数组\(d_x\)加上1,\(d_y\)加上1,\(lca(x,y)\)减去1,\(fa_{lac(x,y)}\)减去1
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<deque>
#include<cstdlib>
#include<ctime>
#define dd double
#define ld long double
#define ll long long
#define ull unsigned long long
#define N 50100
#define M 100100
using namespace std;
const int INF=0x3f3f3f3f;
inline int Max(int a,int b){
return a>b?a:b;
}
inline void Swap(int &a,int &b){
a^=b;b^=a;a^=b;
}
inline ll read(){
ll 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;
}
struct edge{
int to,next;
inline void intt(int to_,int ne_){
to=to_;next=ne_;
}
};
edge li[M];
int head[N],tail;
inline void add(int from,int to){
li[++tail].intt(to,head[from]);
head[from]=tail;
}
int size[N],fa[N],son[N],top[N],deep[N];
inline void dfs1(int k,int f){
fa[k]=f;size[k]=1;deep[k]=deep[f]+1;
for(int x=head[k];x;x=li[x].next){
int to=li[x].to;
if(to==f) continue;
dfs1(to,k);
size[k]+=size[to];
if(size[son[k]]<size[to]) son[k]=to;
}
}
inline void dfs2(int k,int t){
top[k]=t;
if(son[k]) dfs2(son[k],t);
for(int x=head[k];x;x=li[x].next){
int to=li[x].to;
if(to==fa[k]||to==son[k]) continue;
dfs2(to,to);
}
}
inline int lca(int x,int y){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) Swap(x,y);
x=fa[top[x]];
}
if(deep[x]>deep[y]) Swap(x,y);
return x;
}
int n,k,d[N],ans;
inline void dfs(int k){
for(int x=head[k];x;x=li[x].next){
int to=li[x].to;
if(to==fa[k]) continue;
dfs(to);
d[k]+=d[to];
}
ans=Max(ans,d[k]);
}
int main(){
n=read();k=read();
for(int i=1;i<=n-1;i++){
int from=read(),to=read();
add(from,to);add(to,from);
}
dfs1(1,0);dfs2(1,1);
for(int i=1;i<=k;i++){
int a=read(),b=read();
int Lca=lca(a,b);
d[a]++;d[b]++;d[fa[Lca]]--;d[Lca]--;
// printf("lca: %d\n",lca(a,b));
}
dfs(1);
printf("%d",ans);
return 0;
}
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<deque>
#include<cstdlib>
#include<ctime>
#define dd double
#define ld long double
#define ll long long
#define ull unsigned long long
#define N 300100
#define M 600100
using namespace std;
const int INF=0x3f3f3f3f;
inline void Swap(int &a,int &b){
a^=b;b^=a;a^=b;
}
inline ll read(){
ll 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;
}
struct edge{
int to,next;
inline void intt(int to_,int ne_){
to=to_;next=ne_;
}
};
edge li[M];
int head[N],tail;
inline void add(int from,int to){
li[++tail].intt(to,head[from]);
head[from]=tail;
}
int size[N],fa[N],son[N],top[N],deep[N];
inline void dfs1(int k,int f){
fa[k]=f;size[k]=1;deep[k]=deep[f]+1;
for(int x=head[k];x;x=li[x].next){
int to=li[x].to;
if(to==f) continue;
dfs1(to,k);
size[k]+=size[to];
if(size[son[k]]<size[to]) son[k]=to;
}
}
inline void dfs2(int k,int t){
top[k]=t;
if(son[k]) dfs2(son[k],t);
for(int x=head[k];x;x=li[x].next){
int to=li[x].to;
if(to==fa[k]||to==son[k]) continue;
dfs2(to,to);
}
}
inline int lca(int x,int y){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) Swap(x,y);
x=fa[top[x]];
}
if(deep[x]>deep[y]) Swap(x,y);
return x;
}
int n,a[N],d[N],rk[N];
inline void dfs(int k){
for(int x=head[k];x;x=li[x].next){
int to=li[x].to;
if(to==fa[k]) continue;
dfs(to);
d[k]+=d[to];
}
}
int main(){
n=read();
for(int i=1;i<=n;i++){
a[i]=read();
// rk[a[i]]=i;
}
for(int i=1;i<=n-1;i++){
int from=read(),to=read();
add(from,to);add(to,from);
}
dfs1(1,0);dfs2(1,1);
for(int i=1;i<=n-1;i++){
int Lca=lca(a[i],a[i+1]),x=a[i],y=a[i+1];
// printf("lca: %d\n",Lca);
d[x]++;d[y]++;d[Lca]--;d[fa[Lca]]--;
}
dfs(1);
for(int i=2;i<=n;i++) d[a[i]]--;
for(int i=1;i<=n;i++) printf("%d\n",d[i]);
return 0;
}