제출 #1250009

#제출 시각아이디문제언어결과실행 시간메모리
1250009g4yuhgConstruction of Highway (JOI18_construction)C++20
100 / 100
256 ms158888 KiB
//Huyduocdithitp
#include <bits/stdc++.h>
typedef long long ll;
#define pii pair<ll, ll> 
#define fi first
#define se second
#define TASK "mansion"
#define start if(fopen(TASK".in","r")){freopen(TASK".in","r",stdin);freopen(TASK".out","w",stdout);}
#define faster ios_base::sync_with_stdio(false);cin.tie(NULL);
#define N 200005
#define endl '\n'
using namespace std;

ll n, c[N], par[N], bit[N], m;
pii canh[N];

void update(ll u, ll v) {
	ll idx = u;
	while (idx <= m) {
		bit[idx] += v;
		idx += idx & (-idx);
	}
}

ll get(ll u) {
	ll idx = u, ans = 0;
	while (idx > 0) {
		ans += bit[idx];
		idx -= idx & (-idx);
	}
	return ans;
}

vector<ll> ns;

vector<ll> adj[N];

ll cur_chain, cur_pos, chain_head[N], chain_id[N], tour[N], pos[N], sz[N], high[N];

stack<pii> st[N]; // stack cua nhung con cha, no se luon la con dau chain

void dfs(ll u, ll parent) {
	sz[u] = 1;
	for (auto v : adj[u]) {
		if (v == parent) continue;
		par[v] = u;
		high[v] = high[u] + 1;
		dfs(v, u);
		sz[u] += sz[v];
	}
}

void hld(ll u, ll parent) {
	if (chain_head[cur_chain] == 0) {
		chain_head[cur_chain] = u;
	}
	pos[u] = cur_pos;
	tour[cur_pos] = u;
	cur_pos ++ ;
	chain_id[u] = cur_chain;
	ll nxt = 0;
	for (auto v : adj[u]) {
		if (v == parent) continue;
		if (sz[v] > sz[nxt]) {
			nxt = v;
		}
	}
	if (nxt) {
		hld(nxt, u);
	}
	for (auto v : adj[u]) {
		if (v == parent || v == nxt) continue;
		cur_chain ++ ;
		hld(v, u);
	}
}

vector<pii> vt, vt1; // xet.fi luu gia tri, xet.se luu so con

void lay(ll u, ll v, bool first) {
	ll ugoc = u;
	ll root = chain_head[chain_id[u]];
	ll socon = high[u] - high[root] + 1;
	if (first && chain_id[u] == chain_id[v]) socon ++ ;
	while (st[root].size() && socon > 0) {
		pii xet = st[root].top(); st[root].pop();
		ll x = min(socon, xet.se);
		vt.push_back({xet.fi, x});
		socon -= x;
		xet.se -= x;
		if (xet.se > 0) {
			st[root].push(xet);
		}
		if (socon == 0) break;
	}
	if (first) {
		if (chain_id[u] == chain_id[v]) {
			st[root].push({c[v], high[u] - high[root] + 2});
		}
		else {
			st[root].push({c[v], high[u] - high[root] + 1});
			ll root_v = chain_head[chain_id[v]];
			if (st[root_v].size()) {
				st[root_v].top().se -- ;
				if (st[root_v].top().se == 0) st[root_v].pop();
			}
			st[root_v].push({c[v], 1});
		}
		return;
	}
	st[root].push({c[v], high[u] - high[root] + 1});
}

void cv(ll u, ll v) {
	ll ugoc = u;
	//cout << "u v " << u << " " << v << endl; 
	// di tu u len cha
	bool first = 1;
	while (true) {
		if (u == 0) break;
		vt.clear();
		lay(u, v, first);
		first = 0;
		for (int i = vt.size() - 1; i >= 0; i --) {
			vt1.push_back(vt[i]);
		}
		u = par[chain_head[chain_id[u]]];
		if (u == 0) break;
	}
	ll ans = 0;
	for (int i = 0; i < vt1.size(); i ++) {
		pii xet = vt1[i];
		ll to = get(xet.fi - 1);
		ans += to * xet.se;
		update(xet.fi, xet.se);
	}
	for (int i = 0; i < vt1.size(); i ++) {
		pii xet = vt1[i];
		update(xet.fi, -xet.se);
	}
	vt1.clear();
	vt.clear();
	cout << ans << endl;
}

void pre() {
	cur_chain = cur_pos = 1;
	dfs(1, 1);
	hld(1, 1);
	sort(ns.begin(), ns.end());
	ns.resize(unique(ns.begin(), ns.end()) - ns.begin());
	m = ns.size();
	for (int i = 1; i <= n; i ++) {
		c[i] = lower_bound(ns.begin(), ns.end(), c[i]) - ns.begin() + 1;
	}
	for (int i = 1; i <= n - 1; i ++) {
		cv(canh[i].fi, canh[i].se);
	}
}

signed main() {
	
    faster;
    
    cin >> n;
    
    for (int i = 1; i <= n; i ++) {
    	cin >> c[i];
    	ns.push_back(c[i]);
    }
    
    for (int i = 1; i <= n - 1; i ++) {
    	cin >> canh[i].fi >> canh[i].se;
    	adj[canh[i].fi].push_back(canh[i].se);
    	adj[canh[i].se].push_back(canh[i].fi);
    }
    
    pre();
    
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...