This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
//Then
#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define faster ios_base::sync_with_stdio(0); cin.tie(0);
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair <int, int>;
mt19937_64 Rand(chrono::steady_clock::now().time_since_epoch().count());
const int maxN = 1e5 + 1;
//const int Mod = 1e9 + 7;
//const int inf =
int n;
int a[maxN], b[maxN], c[maxN];
struct TSeg{
int l, r, t;
};
deque <TSeg> S[maxN];
vector <int> adj[maxN];
int head[maxN], id[maxN], num[maxN];
int child[maxN], depth[maxN], par[maxN];
int timedfs, cnt = 1;
vector <int> node;
struct TBIT{
int bit[maxN];
TBIT(){
memset(bit, 0, sizeof(bit));
}
void update(int x, int v){
for (; x <= n; x += x & -x){
bit[x] += v;
}
}
int get(int x){
int res = 0;
for (; x; x -= x & -x){
res += bit[x];
}
return res;
}
};
TBIT bit;
void dfs(int u, int p){
depth[u] = depth[p] + 1;
par[u] = p;
for (int i: adj[u]){
dfs(i, u);
child[u] += child[i] + 1;
}
}
void hld(int u){
num[u] = ++timedfs;
if (!head[cnt]) head[cnt] = u;
id[u] = cnt;
pii maxx = {-1, -1};
for (int i: adj[u]){
maxx = max(maxx, {child[i], i});
}
if (maxx.se != -1){
hld(maxx.se);
}
for (int i: adj[u]){
if (i == maxx.se) continue;
++cnt;
hld(i);
}
}
ll query(int u, int v){
ll res = 0;
vector <TSeg> save;
while (u){
int p = id[u];
vector <TSeg> tem;
while (!S[p].empty() && S[p].back().r <= num[u]){
tem.pb(S[p].back());
S[p].pop_back();
}
if (!S[p].empty() && S[p].back().l <= num[u]){
tem.pb({S[p].back().l, num[u], S[p].back().t});
S[p].back().l = num[u] + 1;
}
reverse(tem.begin(), tem.end());
for (auto i: tem){
res += 1LL * (i.r - i.l + 1) * bit.get(i.t - 1);
bit.update(i.t, i.r - i.l + 1);
}
move(tem.begin(), tem.end(), back_inserter(save));
S[p].pb({num[head[p]], num[u], c[v]});
u = par[head[p]];
}
for (auto i: save){
bit.update(i.t, i.l - i.r - 1);
}
S[id[v]].push_front({num[v], num[v], c[v]});
return res;
}
void Init(){
cin >> n;
for (int i = 1; i <= n; ++i){
cin >> c[i];
node.pb(c[i]);
}
sort(node.begin(), node.end());
node.resize(unique(node.begin(), node.end()) - node.begin());
for (int i = 1; i <= n; ++i){
c[i] = upper_bound(node.begin(), node.end(), c[i]) - node.begin();
}
for (int i = 1; i < n; ++i){
cin >> a[i] >> b[i];
adj[a[i]].pb(b[i]);
}
dfs(1, 0);
hld(1);
S[1].pb({1, 1, c[1]});
for (int i = 1; i < n; ++i){
cout << query(a[i], b[i]) << "\n";
}
}
#define debug
#define taskname "test"
signed main(){
faster
if (fopen(taskname".inp", "r")){
freopen(taskname".inp", "r", stdin);
freopen(taskname".out", "w", stdout);
}
int tt = 1;
//cin >> tt;
while (tt--){
Init();
}
if (fopen("timeout.txt", "r")){
ofstream timeout("timeout.txt");
timeout << signed(double(clock()) / CLOCKS_PER_SEC * 1000);
timeout.close();
#ifndef debug
cerr << "Time elapsed: " << signed(double(clock()) / CLOCKS_PER_SEC * 1000) << "ms\n";
#endif // debug
}
}
Compilation message (stderr)
construction.cpp: In function 'int main()':
construction.cpp:133:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
133 | freopen(taskname".inp", "r", stdin);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
construction.cpp:134:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
134 | freopen(taskname".out", "w", stdout);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |