刚学OI 1e-INF 秒的蒟蒻求助树上差分45pts

P1600 [NOIP2016 提高组] 天天爱跑步

Sharpsmile @ 2022-07-19 11:29:52

RT

//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <math.h>
#include <algorithm>
#include <istream>
#include <string>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <string.h>
#include <map>
#include <unordered_map>
#include <sstream>
#define mp(a,b) make_pair(a,b)
#define p1(x) x.first
#define p2(x) x.second
#define double long double
#define int long long
using namespace std;
int n;
int m;
int w[300200];
int t1[300200],t3[600200];
int* t2=t3+300100;
int cts[300100];
vector<int>g[300100],cte[300100],ctl[300200];
int fa[300100][21];
int dep[300100];
int s[300100],t[300200],l[300200],len[300200];
inline void dfs(int u){
    dep[u]=dep[fa[u][0]]+1;
    for(int i=1;i<=20;i++)
        fa[u][i]=fa[fa[u][i-1]][i-1];
    for(int v:g[u])
        if(v!=fa[u][0]){
            fa[v][0]=u;
            dfs(v);
        }
}
inline int LCA(int u,int v){
    int l=20;
    if(dep[u]<dep[v])swap(u,v);
    while(dep[u]>dep[v]){
        if(dep[fa[u][l]]>=dep[v])
            u=fa[u][l];
        l--;
    }
    if(u==v)return u;
    l=20;
    while(l>=0){
        if(fa[u][l]!=fa[v][l])u=fa[u][l],v=fa[v][l];
        l--;
    }
    return fa[u][0];
}
inline int LEN(int u,int v){
    int l=20;
    int res=0;
       if(dep[u]<dep[v])swap(u,v);
       while(dep[u]>dep[v]){
           if(dep[fa[u][l]]>=dep[v])
               u=fa[u][l],res+=1<<l;
           l--;
       }
       if(u==v)return res;
       l=20;
       while(l>=0){
           if(fa[u][l]!=fa[v][l])u=fa[u][l],v=fa[v][l],res+=1<<l+1;
           l--;
       }
       return res+2;
}
int ans[300200];
inline void calc(int u){
    int s1=t1[dep[u]+w[u]],s2=t2[w[u]-dep[u]];
    for(int v:g[u])
        if(v!=fa[u][0])calc(v);
    t1[dep[u]]+=cts[u];
    for(int i:cte[u])
        t2[len[i]-dep[t[i]]]++;
    ans[u]+=t1[dep[u]-s1+w[u]]+t2[w[u]-dep[u]]-s2;
    for(int i:ctl[u])
        t1[dep[s[i]]]--,t2[len[i]-dep[t[i]]]--;
}
signed main(){
    ios::sync_with_stdio(false);
    freopen("/Users/noip2019/Downloads/P1600_3.in","r",stdin);
    cin>>n>>m;
    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    for(int i=1;i<=n;i++)cin>>w[i];
    dep[0]=-1;
    dfs(1);
    for(int i=1;i<=m;i++){
        cin>>s[i];
        cin>>t[i];
        l[i]=LCA(s[i],t[i]);
        len[i]=LEN(s[i],t[i]);
        ctl[l[i]].push_back(i);
        cts[s[i]]++;
        cte[t[i]].push_back(i);
        if(dep[s[i]]-dep[l[i]]==w[l[i]])ans[l[i]]--;
    }
    calc(1);
    for(int i=1;i<=n;i++)cout<<ans[i]<<" ";
    return 0;
}

by Sharpsmile @ 2022-07-19 11:36:36

我是sb,此贴终


by PassName @ 2022-07-19 11:43:10

@Jocker_CW 言简意赅,简洁明了


by Sharpsmile @ 2022-07-19 11:50:52

@单南松 就差分能把进子树之前的值减进下标里不是sb是什么(

 int s1=t1[dep[u]+w[u]],s2=t2[w[u]-dep[u]];
。。。。。。
ans[u]+=t1[dep[u]-s1+w[u]]+t2[w[u]-dep[u]]-s2;

by PassName @ 2022-07-19 11:54:04

@Jocker_CW 。。。。。。


|