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";
}