Loading

树上差分

树上差分

顾名思义,就是对树上路径或子树和整体加减时可以利用树上差分。

当然也可以线段树维护(树链剖分)

例如,要让x到y的这段路径上所以节点加1

就让我们差分数组\(d_x\)加上1,\(d_y\)加上1,\(lca(x,y)\)减去1,\(fa_{lac(x,y)}\)减去1

例题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;
}

例题2

代码:

#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;
}
posted @ 2021-04-05 15:59  hyl天梦  阅读(92)  评论(0编辑  收藏  举报