P2664 线段树合并题解
HDS_Acenaphthylene · · 题解
第三种情况中,
线段树合并
#include<bits/stdc++.h>
#define debug(x) cerr << #x << ": " << x << '\n';
#define rep(i, a, b) for (int i = (a); i <= (b); i++)
#define lop(i, a, b) for (int i = (a); i < (b); i++)
#define dwn(i, a, b) for (int i = (a); i >= (b); i--)
#define elif else if
#define iosfst ios::sync_with_stdio(0);cin.tie(0), cout.tie(0)
#define pb push_back
#define _if (
#define _then ?(
#define _els ):
#define _end )
#define intt long long
using namespace std;
#define N 100005
bool mem1;
vector<int>g[N];
int n, fa[N], a[N], sz[N];intt val[N], ans[N];
namespace sgt{
int tp, ls[N * 32], rs[N * 32], fa[N * 32];intt tr[N * 32];
int rt[N * 32];
inline void pushup(int p) {
tr[p] = tr[ls[p]] + tr[rs[p]];
}
inline void upd(int p, int l, int r, int x, intt v) {
if(l == r) {
tr[p] += v;
return ;
}
int mid = (l + r) >> 1;
if(x <= mid) {
if(!ls[p]) {
ls[p] = ++ tp;
fa[tp] = p;
}
upd(ls[p], l, mid, x, v);
}
else {
if(!rs[p]) {
rs[p] = ++ tp;
fa[tp] = p;
}
upd(rs[p], mid + 1, r, x, v);
}
pushup(p);
}
inline void set(int p, int l, int r, intt x, intt v) {
if(l == r) {
tr[p] = v;
return ;
}
int mid = (l + r) >> 1;
if(x <= mid) {
if(!ls[p]) {
ls[p] = ++ tp;
fa[tp] = p;
}
set(ls[p], l, mid, x, v);
}
else {
if(!rs[p]) {
rs[p] = ++ tp;
fa[tp] = p;
}
set(rs[p], mid + 1, r, x, v);
}
pushup(p);
//cout << "Set " << x << " " << v << "\n";
//cout << p << " " << l << " " << r << " " << tr[p] << "\n";
}
inline int merge(int p1, int p2) {
if(!p1 || !p2) return p1 | p2;
ls[p1] = merge(ls[p1], ls[p2]);
rs[p1] = merge(rs[p1], rs[p2]);
tr[p1] += tr[p2];
return p1;
}
inline int qry(int p, int l, int r, intt x) {
if(l == r)
return tr[p];
int mid = (l + r) >> 1;
if(x <= mid) {
if(!ls[p])
return 0;
return qry(ls[p], l, mid, x);
}
else {
if(!rs[p])
return 0;
return qry(rs[p], mid + 1, r, x);
}
}
}
bool mem2;
void dfs(int u, int f) {
fa[u] = f;
sz[u] = 1;
for(auto v : g[u])
if(v != f)
dfs(v, u),
sgt::rt[u] = sgt::merge(sgt::rt[u], sgt::rt[v]),
sz[u] += sz[v];
if(sgt::rt[u] == 0)
sgt::rt[u] = ++sgt::tp;
sgt::set(sgt::rt[u], 1, 1000000, a[u], sz[u]);
if(f)
val[u] = sgt::qry(sgt::rt[u], 1, 1000000, a[f]);
}
void dfs2(int u, int f) {
//cout << "DFS2 " << u << " " << f << "\n";
if(u == 1) {
for(auto v : g[u])
dfs2(v, u);
return ;
}
intt rbp = sgt::qry(sgt::rt[1], 1, 1000000, a[u]);
intt rdx = sgt::qry(sgt::rt[1], 1, 1000000, a[f]);
sgt::set(sgt::rt[1], 1, 1000000, a[u], n);
sgt::set(sgt::rt[1], 1, 1000000, a[f], n - sz[u] + val[u]);
ans[u] = sgt::tr[sgt::rt[1]];
for(auto v: g[u])
if(f != v)
dfs2(v, u);
sgt::set(sgt::rt[1], 1, 1000000, a[u], rbp);
sgt::set(sgt::rt[1], 1, 1000000, a[f], rdx);
}
signed main() {
iosfst;
cin >> n;
rep(i, 1, n) cin >> a[i];
lop(i, 1, n) {
int x, y;
cin >> x >> y;
g[x].pb(y);
g[y].pb(x);
}
dfs(1, 0);
ans[1] = sgt::tr[sgt::rt[1]];
dfs2(1, 0);
rep(i, 1, n)
cout << ans[i] << "\n";
}