做题记录:P1600 [NOIP 2016 提高组] 天天爱跑步
这题可以发现我们的人是从 \(x\) 到 \(lca(x,y)\) 再到 \(y\) 的,所以可以分两段考虑。
然后每一段都可以用线段树合并计算。
做完了。
#include<bits/stdc++.h>
using namespace std;
// #define int long long
#define N 300010
int n,m,tr[N],f[N][20],tot,a[N],dep[N],ans[N];
vector<int>to[N];
vector<pair<int,int>>chg[N];
struct stu{
int ls,rs,sum;
}t[N<<5];
struct node{
int x,y,lca;
}q[N];
void pushup(int p){
t[p].sum=0;
if(t[p].ls){
t[p].sum+=t[t[p].ls].sum;
}
if(t[p].rs){
t[p].sum+=t[t[p].rs].sum;
}
}
int merge(int rta,int rtb,int l,int r){
if(!rta){
return rtb;
}
if(!rtb){
return rta;
}
if(l==r){
t[rta].sum+=t[rtb].sum;
return rta;
}
int mid=(l+r)>>1;
t[rta].ls=merge(t[rta].ls,t[rtb].ls,l,mid);
t[rta].rs=merge(t[rta].rs,t[rtb].rs,mid+1,r);
pushup(rta);
return rta;
}
int add(int p,int x,int l,int r,int k){
if(!p){
p=++tot;
}
if(l==r){
t[p].sum+=k;
return p;
}
int mid=(l+r)>>1;
if(x<=mid){
t[p].ls=add(t[p].ls,x,l,mid,k);
}
else{
t[p].rs=add(t[p].rs,x,mid+1,r,k);
}
pushup(p);
return p;
}
int ask(int p,int x,int l,int r){
if(!p){
return 0;
}
if(l==r){
return t[p].sum;
}
int mid=(l+r)>>1;
if(x<=mid){
if(t[p].ls){
return ask(t[p].ls,x,l,mid);
}
return 0;
}
else{
if(t[p].rs){
return ask(t[p].rs,x,mid+1,r);
}
return 0;
}
}
void init(int x,int fa){
f[x][0]=fa;
for(int i=1;i<=19;i++){
f[x][i]=f[f[x][i-1]][i-1];
}
dep[x]=dep[fa]+1;
for(auto y:to[x]){
if(y==fa){
continue;
}
init(y,x);
}
}
int lca(int x,int y){
if(x==y){
return x;
}
if(dep[x]<dep[y]){
swap(x,y);
}
for(int i=19;i>=0;i--){
if(dep[f[x][i]]>=dep[y]){
x=f[x][i];
}
}
if(x==y){
return x;
}
for(int i=19;i>=0;i--){
if(f[x][i]!=f[y][i]){
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
void dfs(int x,int fa){
for(auto y:to[x]){
if(y==fa){
continue;
}
dfs(y,x);
tr[x]=merge(tr[x],tr[y],1,3*n);
}
for(auto [op,pos]:chg[x]){
tr[x]=add(tr[x],pos,1,3*n,op);
}
ans[x]+=ask(tr[x],dep[x]+a[x],1,3*n);
}
void dfs2(int x,int fa){
for(auto y:to[x]){
if(y==fa){
continue;
}
dfs2(y,x);
tr[x]=merge(tr[x],tr[y],1,3*n);
}
for(auto [op,pos]:chg[x]){
tr[x]=add(tr[x],pos,1,3*n,op);
}
ans[x]+=ask(tr[x],a[x]-dep[x]+2*n,1,3*n);
}
signed main(){
cin>>n>>m;
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
to[u].push_back(v);
to[v].push_back(u);
}
init(1,0);
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=m;i++){
cin>>q[i].x>>q[i].y;
q[i].lca=lca(q[i].x,q[i].y);
chg[q[i].x].push_back(make_pair(1,dep[q[i].x]));
chg[f[q[i].lca][0]].push_back(make_pair(-1,dep[q[i].x]));
}
dfs(1,0);
for(int i=1;i<=tot;i++){
t[i].ls=t[i].rs=t[i].sum=0;
}
tot=0;
for(int i=1;i<=n;i++){
tr[i]=0;
chg[i].clear();
}
for(int i=1;i<=m;i++){
chg[q[i].y].push_back(make_pair(1,dep[q[i].x]-2*dep[q[i].lca]+2*n));
chg[q[i].lca].push_back(make_pair(-1,dep[q[i].x]-2*dep[q[i].lca]+2*n));
}
dfs2(1,0);
for(int i=1;i<=n;i++){
cout<<ans[i]<<' ';
}
cout<<'\n';
return 0;
}

浙公网安备 33010602011771号