Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma comment(linker, "/STACK:512000000")
- #define _CRT_SECURE_NO_WARNINGS
- //#include "testlib.h"
- #include <cstdio>
- #include <cassert>
- #include <algorithm>
- #include <iostream>
- #include <memory.h>
- #include <string>
- #include <vector>
- #include <set>
- #include <map>
- #include <cmath>
- #include <bitset>
- #include <deque>
- #include <ctime>
- #include <stack>
- #include <queue>
- #include <fstream>
- #include <sstream>
- //#include <unordered_map>
- using namespace std;
- //#define FILENAME ""
- #define mp make_pair
- #define all(a) a.begin(), a.end()
- typedef long long li;
- typedef long double ld;
- void solve();
- void precalc();
- clock_t start;
- //int timer = 1;
- int testNumber = 1;
- bool todo = true;
- int main() {
- #ifdef room111
- freopen("in.txt", "r", stdin);
- //freopen("out.txt", "w", stdout);
- #else
- //freopen("input.txt", "r", stdin);
- //freopen("output.txt", "w", stdout);
- //freopen(FILENAME".in", "r", stdin);
- //freopen(FILENAME ".out", "w", stdout);
- #endif
- start = clock();
- int t = 1;
- cout.sync_with_stdio(0);
- cin.tie(0);
- precalc();
- cout.precision(10);
- cout << fixed;
- //cin >> t;
- int testNum = 1;
- while (t--) {
- //cerr << testNum << endl;
- //cout << "Case #" << testNum++ << ": ";
- solve();
- ++testNumber;
- //++timer;
- }
- #ifdef room111
- cerr << "\n\n" << (clock() - start) / 1.0 / CLOCKS_PER_SEC << "\n\n";
- #endif
- return 0;
- }
- //BE CAREFUL: IS INT REALLY INT?
- //#define int li
- /*int pr[] = { 97, 2011 };
- int mods[] = { 1000000007, 1000000009 };
- const int C = 300500;
- int powers[2][C];*/
- //int MOD = 1000000007;
- //int c[5010][5010];
- template<typename T>
- T binpow(T q, T w, T mod) {
- if (!w)
- return 1 % mod;
- if (w & 1)
- return q * 1LL * binpow(q, w - 1, mod) % mod;
- return binpow(q * 1LL * q % mod, w / 2, mod);
- }
- /*int curMod = 1000000009;
- int fact[100500], revfact[100500];
- int getC(int n, int k) {
- int res = fact[n] * revfact[n - k] % curMod * revfact[k] % curMod;
- return res;
- }*/
- /*const int C = 7000500;
- int least_prime[C];*/
- void precalc() {
- /*for (int i = 2; i < C; ++i) {
- if (!least_prime[i]) {
- least_prime[i] = i;
- for (li j = i * 1LL * i; j < C; j += i) {
- least_prime[j] = i;
- }
- }
- }*/
- /*fact[0] = revfact[0] = 1;
- for (int i = 1; i < 100500; ++i) {
- fact[i] = fact[i - 1] * i % curMod;
- revfact[i] = binpow(fact[i], curMod - 2, curMod);
- }*/
- /*for (int w = 0; w < 2; ++w) {
- powers[w][0] = 1;
- for (int j = 1; j < C; ++j) {
- powers[w][j] = (powers[w][j - 1] * 1LL * pr[w]) % mods[w];
- }
- }*/
- /*for (int i = 0; i < 5010; ++i) {
- c[i][i] = c[i][0] = 1;
- for (int j = 1; j < i; ++j) {
- c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % MOD;
- }
- }*/
- }
- template<typename T>
- T gcd(T q, T w) {
- while (w) {
- q %= w;
- swap(q, w);
- }
- return q;
- }
- template<typename T>
- T lcm(T q, T w) {
- return q / gcd(q, w) * w;
- }
- //#define int li
- //const int mod = 1000000007;
- class Treap {
- public:
- typedef struct _node {
- int key;
- int cnt;
- int prior;
- _node* l;
- _node* r;
- _node(int key) :key(key), l(nullptr), r(nullptr), cnt(1) { prior = (rand() << 16) | rand(); }
- void push() {
- }
- void recalc() {
- cnt = 1 + Cnt(l) + Cnt(r);
- }
- static int Cnt(_node* v) {
- if (!v)
- return 0;
- return v->cnt;
- }
- }*node;
- static int Cnt(node v) {
- if (!v)
- return 0;
- return v->cnt;
- }
- node root;
- node merge(node l, node r) {
- if (!l)
- return r;
- if (!r)
- return l;
- if (l->prior < r->prior) {
- l->push();
- l->r = merge(l->r, r);
- l->recalc();
- return l;
- }
- else {
- r->push();
- r->l = merge(l, r->l);
- r->recalc();
- return r;
- }
- }
- void split(node v, int key, node& l, node& r) {
- l = r = nullptr;
- if (!v)
- return;
- v->push();
- if (v->key < key) {
- l = v;
- split(l->r, key, l->r, r);
- l->recalc();
- }
- else {
- r = v;
- split(r->l, key, l, r->l);
- r->recalc();
- }
- }
- void splitCnt(node v, int idx, node& l, node& r) {
- l = r = nullptr;
- if (!v)
- return;
- v->push();
- if (Cnt(v->l) < idx) {
- l = v;
- splitCnt(l->r, idx - Cnt(v->l) - 1, l->r, r);
- l->recalc();
- }
- else {
- r = v;
- splitCnt(r->l, idx, l, r->l);
- r->recalc();
- }
- }
- public:
- Treap() {
- root = nullptr;
- }
- size_t size() const {
- return Cnt(root);
- }
- int get_before(int L) {
- node l, r;
- split(root, L, l, r);
- int res = Cnt(l);
- root = merge(l, r);
- return res;
- }
- node erase_min() {
- node l, r;
- splitCnt(root, 1, l, r);
- root = r;
- return l;
- }
- void insert(int key) {
- node l = nullptr, r = nullptr;
- split(root, key, l, r);
- node cur_node = new _node(key);
- root = merge(merge(l, cur_node), r);
- }
- void insert(node v) {
- node l = nullptr, r = nullptr;
- split(root, v->key, l, r);
- root = merge(merge(l, v), r);
- }
- void merge(Treap cur) {
- while (cur.size() > 0) {
- node now = cur.erase_min();
- now->cnt = 1;
- now->l = now->r = nullptr;
- insert(now);
- }
- }
- };
- typedef Treap::node Node;
- vector<vector<int>> g;
- vector<int> a;
- vector<int> down_more, up_more;
- vector<vector<int>> nei_more;
- vector<li> sum_down;
- Treap dfs(int v, int p) {
- sum_down[v] = 0;
- int pref = 0;
- Treap res;
- for (int i = 0; i < g[v].size(); ++i) {
- int to = g[v][i];
- if (to == p) {
- continue;
- }
- Treap nex = dfs(to, v);
- if (nex.size() > res.size()) {
- swap(nex, res);
- }
- res.merge(nex);
- sum_down[v] += sum_down[to];
- int cur = res.get_before(a[v]);
- nei_more[v][i] = cur - pref;
- pref = cur;
- }
- down_more[v] = res.get_before(a[v]);
- sum_down[v] += down_more[v];
- res.insert(a[v]);
- return res;
- }
- li best_sum = 1e18;
- int best_v = -1;
- void dfs_res(int v, int p, li sum_up) {
- li cur_res = sum_down[v] + sum_up + up_more[v];
- if (cur_res < best_sum || cur_res == best_sum && best_v > v) {
- best_sum = cur_res;
- best_v = v;
- }
- for (int i = 0; i < g[v].size(); ++i) {
- int to = g[v][i];
- if (to == p) {
- continue;
- }
- li new_up = sum_up + up_more[v] + sum_down[v] - sum_down[to] - nei_more[v][i];
- dfs_res(to, v, new_up);
- }
- }
- void solve() {
- int n;
- n = 200000;
- cin >> n;
- g.resize(n);
- a.resize(n);
- for (int i = 0; i < n; ++i) {
- cin >> a[i];
- //a[i] = i + 1;
- a[i] = n - a[i];
- }
- for (int i = 1; i < n; ++i) {
- int u, v;
- //u = (i + 1) / 2; v = i + 1;
- cin >> u >> v;
- --u; --v;
- g[u].push_back(v);
- g[v].push_back(u);
- }
- down_more.resize(n);
- up_more.resize(n);
- sum_down.resize(n);
- nei_more.resize(n);
- for (int i = 0; i < n; ++i) {
- nei_more[i].assign(g[i].size(), -1);
- }
- Treap tree = dfs(0, 0);
- for (int i = 0; i < n; ++i) {
- up_more[i] = tree.get_before(a[i]) - down_more[i];
- for (int j = 0; j < g[i].size(); ++j) {
- if (nei_more[i][j] == -1) {
- nei_more[i][j] = up_more[i];
- }
- }
- }
- dfs_res(0, 0, 0);
- cout << best_v + 1 << ' ' << best_sum << "\n";
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement