【廣西省賽#6】F.Forever_Young

PaperCloud發表於2024-10-26

Description

對於樹上每個點詢問

\[\sum_{x\in subtree_o}\sum_{y\in subtree_o} \min\{|a_x-a_y|, |b_x-b_y|\} \]

Solution

\(|a_x-a_y|\) 的和加上 \(|b_x-b_y|\) 的和,減去切比雪夫距離,轉成曼哈頓距離來做。對於每一部分,進行線段樹合併。

Code

#include "bits/stdc++.h"
using namespace std;
using ui=unsigned; using db=long double; using ll=long long; using ull=unsigned long long; using lll=__int128;
using pii=pair<int,int>; using pll=pair<ll,ll>;
template<class T1, class T2> istream &operator>>(istream &cin, pair<T1, T2> &a) { return cin>>a.first>>a.second; }
template <std::size_t Index=0, typename... Ts> typename std::enable_if<Index==sizeof...(Ts), void>::type tuple_read(std::istream &is, std::tuple<Ts...> &t) { }
template <std::size_t Index=0, typename... Ts> typename std::enable_if<Index < sizeof...(Ts), void>::type tuple_read(std::istream &is, std::tuple<Ts...> &t) { is>>std::get<Index>(t); tuple_read<Index+1>(is, t); }
template <typename... Ts>std::istream &operator>>(std::istream &is, std::tuple<Ts...> &t) { tuple_read(is, t); return is; }
template<class T1> istream &operator>>(istream &cin, vector<T1> &a) { for (auto &x:a) cin>>x; return cin; }
template<class T1> istream &operator>>(istream &cin, valarray<T1> &a) { for (auto &x:a) cin>>x; return cin; }
template<class T1, class T2> bool cmin(T1 &x, const T2 &y) { if (y<x) { x=y; return 1; } return 0; }
template<class T1, class T2> bool cmax(T1 &x, const T2 &y) { if (x<y) { x=y; return 1; } return 0; }
istream &operator>>(istream &cin, lll &x) { x=0; static string s; cin>>s; for (char c:s) x=x*10+(c-'0'); return cin; }
ostream &operator<<(ostream &cout, lll x) { static char s[60]; int tp=1; s[0]='0'+(x%10); while (x/=10) s[tp++]='0'+(x%10); while (tp--) cout<<s[tp]; return cout; }
#if !defined(ONLINE_JUDGE)
#include "my_header/IO.h"
#include "my_header/defs.h"
#else
#define dbg(...) ;
#define dbgx(...) ;
#define dbg1(x) ;
#define dbg2(x) ;
#define dbg3(x) ;
#define DEBUG(msg) ;
#define REGISTER_OUTPUT_NAME(Type, ...) ;
#define REGISTER_OUTPUT(Type, ...) ;
#endif
#define all(x) (x).begin(),(x).end()
#define print(...) cout<<format(__VA_ARGS__)
#define err(...) cerr<<format(__VA_ARGS__)
const int mod1 = 998244353, mod2 = 1e9+7;
// #define MOD1
#ifdef MOD1
const int p = mod1; int fpow(int x,ll y,int m=mod1){int r=1;for(;y;y>>=1,x=(ll)x*x%m)if(y&1)r=(ll)r*x%m;return r;}
# else
const int p = mod2; int fpow(int x,ll y,int m=mod2){int r=1;for(;y;y>>=1,x=(ll)x*x%m)if(y&1)r=(ll)r*x%m;return r;}
# endif

const int N=5e5+5;
struct node
{
    ll sum;
    int siz;
    ll ans;
    friend node operator + (const node&x, const node&y) 
    {
        return {(x.sum+y.sum)%p, x.siz+y.siz, ((x.ans+y.ans+(p-x.sum*y.siz%p)+y.sum*x.siz%p)%p+p)%p};
    }
} t[N*20]; int tot;
int ls[N*20], rs[N*20];
int num[N], rt[N];


void add(int &o, int l, int r, int v)
{
    if(!o) t[o=++tot]={0, 0, 0};
    if(l==r)
    {
        t[o].siz++;
        t[o].sum+=num[v];
        t[o].ans=0;
        return ;
    } 
    int mid=(l+r)>>1;
    if(v<=mid) add(ls[o], l, mid, v);
    else add(rs[o], mid+1, r, v);
    t[o]=t[ls[o]]+t[rs[o]];
}
  
void merge(int &x, int y, int l, int r)
{
    if(!y) return;
    if(!x) {x=y; return;}
    if(l==r)
    {
        t[x]=t[x]+t[y];
        return ;
    }
    int mid=(l+r)>>1;
    merge(ls[x], ls[y], l, mid);
    merge(rs[x], rs[y], mid+1, r);
    t[x]=t[ls[x]]+t[rs[x]];
}
  
void build(auto &G, auto &val, int n)
{
    memset(rs, 0, sizeof rs);
    memset(ls, 0, sizeof ls);
    memset(rt, 0, sizeof rt);
    tot=0;
    for(int i=1;i<=n;++i) num[i]=val[i];
    sort(num+1, num+n+1);
    int S=unique(num+1, num+n+1)-num;
    for(int i=1;i<=n;++i) val[i]=lower_bound(num+1, num+S, val[i])-num, assert(val[i]>=1);
    --S;
    for(int i=1;i<=n;++i) add(rt[i], 1, S, val[i]);
  
    function<void(int, int)> dfs = [&](int x, int fa)
    {
        for(auto y : G[x]) if(y!=fa) dfs(y, x);
        for(auto y : G[x]) if(y!=fa) merge(rt[x], rt[y], 1, S);
    };
  
    dfs(1, 0);
}

int main()
{
	ios::sync_with_stdio(0); cin.tie(0);
	cout<<fixed<<setprecision(15);
	int n;
    cin>>n;
    vector G(n+1, vector<int>());
    vector<int> c(n+1), e(n+1), b(n+1), d(n+1);
    for(int i=1;i<n;++i) 
    {
        int x, y;
        cin>>x>>y;
        G[x].push_back(y);
        G[y].push_back(x);
    }
    for(int i=1;i<=n;++i)
    {
        cin>>c[i]>>e[i];
        b[i]=c[i]+e[i];
        d[i]=c[i]-e[i];
    }
  
    vector<int> ans(n+1);
    build(G, c, n);
    for(int i=1;i<=n;++i) ans[i]=t[rt[i]].ans%p;
    build(G, e, n);
    for(int i=1;i<=n;++i) (ans[i]+=t[rt[i]].ans%p)%=p, ans[i]=2ll*ans[i]%p;
    build(G, b, n);
    for(int i=1;i<=n;++i) (ans[i]+=p-t[rt[i]].ans%p)%=p;
    build(G, d, n);
    for(int i=1;i<=n;++i) (ans[i]+=p-t[rt[i]].ans%p)%=p, cout<<ans[i]<<"\n";
  
}

相關文章