洛谷原题链接:P3258 [JLOI2014] 松鼠的新家
化简题意:给定一棵树,进行Q次对(x,y)整条链节点权值+1,输出每个点权值
LCA+树上差分板子
注意:对于2~n个修改的点,每个点计算了两次,所以减一
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=6e5+10;
int h[N],nx[N],to[N],idx=1;
int anst[N][22],c[N],s[N],deep[N];
int a[N];
int n;
void add(int u,int v)
{
to[idx]=v;
nx[idx]=h[u];
h[u]=idx++;
}
void dfs(int u,int fa)
{
deep[u]=deep[fa]+1;
anst[u][0]=fa;
for(int i=h[u];i;i=nx[i])
{
int v=to[i];
if(v==fa) continue;
dfs(v,u);
}
}
void first()
{
for(int j=1;(1<<j)<=n;j++)
{
for(int i=1;i<=n;i++)
{
anst[i][j]=anst[anst[i][j-1]][j-1];
}
}
}
int lca(int x,int y)
{
if(deep[x]<deep[y]) swap(x,y);
int d=deep[x]-deep[y];
for(int j=0;(1<<j)<=d;j++)
{
if((1<<j) & d)
x=anst[x][j];
}
if(x==y) return x;
for(int i=21;i>=0;i--)
{
if(anst[x][i]!=anst[y][i])
{
x=anst[x][i];
y=anst[y][i];
}
if(anst[x][0]==anst[y][0]) break;
}
return anst[x][0];
}
void change(int x,int y)
{
int fa=lca(x,y);
c[x]++;
c[y]++;
c[fa]--;
c[anst[fa][0]]--;
}
void dfs2(int u,int fa)
{
for(int i=h[u];i;i=nx[i])
{
int v=to[i];
if(v==fa) continue;
dfs2(v,u);
s[u]+=s[v];
}
s[u]+=c[u];
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<n;i++)
{
int x,y;
cin>>x>>y;
add(x,y);
add(y,x);
}
dfs(1,0);
first();
for(int i=1;i<n;i++)
{
int x=a[i],y=a[i+1];
change(x,y);
}
dfs2(1,0);
for(int i=2;i<=n;i++) s[a[i]]--;
for(int i=1;i<=n;i++) cout<<s[i]<<endl;
}
浙公网安备 33010602011771号