树上差分

点差分

让x到y所有的点++;
sum[x]++,sum[y]++,sum[lca(x,y)]--,sum[fa[lca(x,y)][0]]--;

边差分

让所有的边下降到点,每个点代表与其父亲连接的点
sum[x]++,sum[y]++,sum[lca(x,y)]-=2;

#include<bits/stdc++.h>
using namespace std;
#define int long long 
const int N=5e5+10;
int fa[N][21],he[3*N],ne[3*N],to[3*N];
int dep[N];
int dex;
int sum[N];
int res=0;
void add(int x,int y)
{
    ++dex;
    ne[dex]=he[x];
    to[dex]=y;
    he[x]=dex;
}
void dfs(int x,int pre)//预处理
{
    dep[x]=dep[pre]+1;
    fa[x][0]=pre;

    for(int i=1;i<=20;i++)
    fa[x][i]=fa[fa[x][i-1]][i-1];
    for(int i=he[x];i;i=ne[i])
    {
        int j=to[i];
        if(j!=pre) dfs(j,x);
    }
}
int lca(int x,int y)//lca
{
    if(dep[x]<dep[y])
    swap(x,y);
    while(dep[x]>dep[y]){
         x = fa[x][(int)log2(dep[x] - dep[y])];
    }
    if(x==y) return x;
    for(int j=20;j>=0;j--)
    {
        if(fa[x][j]!=fa[y][j])
            x=fa[x][j],y=fa[y][j];
    }
    return fa[x][0];
}
void dfs_sum(int x,int pre)
{
    for(int i=he[x];i;i=ne[i])
    {
        int j=to[i];
        if(j!=pre)
        {dfs_sum(j,x);
        sum[x]+=sum[j];}
    }
    res=max(res,sum[x]);
}
void insert(int x, int y)//点差分
 {
      int t = lca(x,y);
      sum[x]++,sum[y]++;
      sum[t]--;
      sum[fa[t][0]]--; 
}
void insert(int x,int y)//边差分
{
    int t = lca(x, y);
    sum[x]++, sum[y]++;
    sum[t]--;
    sum[t]--;
}
signed main( )
{
    int n,m,s;
    int root;
    cin>>n>>m;
    int t=n-1;
    while(t--)
    {
        int x,y;
        cin>>x>>y;
            add(x,y);
            add(y,x);
    }
    dfs(1,0);
    while(m--)
    {
        int x,y;
        cin>>x>>y;
        insert(x,y);
    }
    dfs_sum(1,0);
    cout<<res<<endl;
}
上一篇:[噼昂!]txdy(Pending)


下一篇:P3412 仓鼠找sugar II 题解