Submission #1087624

#TimeUsernameProblemLanguageResultExecution timeMemory
1087624steveonalexConstruction of Highway (JOI18_construction)C++17
100 / 100
405 ms20692 KiB
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; #define MASK(i) (1LL << (i)) #define GETBIT(mask, i) (((mask) >> (i)) & 1) #define ALL(v) (v).begin(), (v).end() #define block_of_code if(true) ll max(ll a, ll b){return (a > b) ? a : b;} ll min(ll a, ll b){return (a < b) ? a : b;} ll gcd(ll a, ll b){return __gcd(a, b);} ll lcm(ll a, ll b){return a / gcd(a, b) * b;} ll LASTBIT(ll mask){return (mask) & (-mask);} int pop_cnt(ll mask){return __builtin_popcountll(mask);} int ctz(ull mask){return __builtin_ctzll(mask);} int logOf(ull mask){return 63 - __builtin_clzll(mask);} mt19937_64 rng(chrono::high_resolution_clock::now().time_since_epoch().count()); ll rngesus(ll l, ll r){return l + (ull) rng() % (r - l + 1);} double rngesus_d(double l, double r){ double cur = rngesus(0, MASK(60) - 1); cur /= MASK(60) - 1; return l + cur * (r - l); } template <class T1, class T2> bool maximize(T1 &a, T2 b){ if (a < b) {a = b; return true;} return false; } template <class T1, class T2> bool minimize(T1 &a, T2 b){ if (a > b) {a = b; return true;} return false; } template <class T> void printArr(T container, string separator = " ", string finish = "\n", ostream &out = cout){ for(auto item: container) out << item << separator; out << finish; } template <class T> void remove_dup(vector<T> &a){ sort(ALL(a)); a.resize(unique(ALL(a)) - a.begin()); } struct FenwickTree{ int n; vector<int> a, b; FenwickTree(int _n){ n = _n; a.resize(n+1); b.resize(n+1); } void assign(int i, int v){ int diff = v - b[i]; update(i, diff); } void update(int i, int v){ b[i] += v; while(i <= n){ a[i] += v; i += LASTBIT(i); } } int get(int i){ int ans = 0; while(i > 0){ ans += a[i]; i -= LASTBIT(i); } return ans; } int binary_search(int v){ if (v == 0) return 0; int p = MASK(logOf(n)), idx = 0; while(p > 0){ if (idx + p <= n && v - a[idx + p] > 0){ idx += p; v -= a[idx]; } p >>= 1; } return idx + 1; } }; struct SegmentTree{ // assign; int query_cnt; int n; vector<pair<int, int>> a; SegmentTree(int _n){ n = _n; a.resize(n * 2 + 2); } void update(int l, int r, int v){ pair<int, int> cur = {++query_cnt, v}; l += n; r += n + 1; while(l < r){ if (l & 1) maximize(a[l++], cur); if (r & 1) maximize(a[--r], cur); l >>= 1; r >>= 1; } } int get(int i){ i += n; pair<int, int> ans = {0, 0}; while(i > 0){ maximize(ans, a[i]); i >>= 1; } return ans.second; } }; const int N = 1e5 + 69; int n; int a[N]; vector<int> graph[N]; int idx[N]; int sz[N], parent[N], h[N]; void find_sz(int u, int p){ sz[u] =1; h[u] = h[p] + 1; parent[u] = p; for(int v: graph[u]) { find_sz(v, u); sz[u] += sz[v]; } } int dfs_cnt = 0; int in[N], head[N]; void decompose(int u, int p, bool flag){ in[u] = ++dfs_cnt; if (flag) head[u] = u; else head[u] = head[p]; pair<int, int> heavy = {-1, -1}; for(int v: graph[u]) maximize(heavy, make_pair(sz[v], v)); if (heavy.second == -1) return; decompose(heavy.second, u, 0); for(int v: graph[u]) if (v != heavy.second) decompose(v, u, 1); } vector<pair<int, int>> get_chain(int u){ vector<pair<int,int>> ans; while(u != 0){ int v = head[u]; ans.push_back({in[v], in[u]}); u = parent[v]; } return ans; } int main(void){ ios::sync_with_stdio(0);cin.tie(0); cout.tie(0); clock_t start = clock(); cin >> n; for(int i = 1; i<=n; ++i) cin >> a[i]; vector<int> X = {0}; for(int i = 1; i<=n; ++i) X.push_back(a[i]); remove_dup(X); for(int i = 1; i<=n; ++i) a[i] = lower_bound(ALL(X), a[i]) - X.begin(); for(int i = 1; i<=n-1; ++i){ int a, b; cin >> a >> b; idx[i] = b; graph[a].push_back(b); } find_sz(1, 0); decompose(1, 0, 1); FenwickTree bit(n); FenwickTree inversion_counter(n); SegmentTree st(n); for(int i = 1; i<=n; ++i) { st.update(in[i], in[i], a[i]); bit.update(i, 1); } for(int i = 1; i<n; ++i){ int v = idx[i]; vector<pair<int,int>> chain = get_chain(parent[v]); vector<pair<int,int>> chim; for(pair<int,int> j: chain){ int u = j.second; while(u >= j.first){ int v = bit.binary_search(bit.get(u)); maximize(v, j.first); bit.assign(v, 0); chim.push_back({u - v + 1, st.get(u)}); u = v - 1; } bit.assign(j.first, 1); bit.assign(j.second + 1, 1); } for(pair<int, int> j: chain) { st.update(j.first, j.second, a[v]); } bit.assign(in[v], 1); bit.assign(in[v], 1); // cout << "Add node: " << v << "\n"; // for(int i = 1; i<=n; ++i) cout << st.get(i) << " "; cout << "\n"; // for(pair<int, int> j: chain) cout << j.first << " " << j.second << "\n"; ll ans = 0; for(pair<int, int> j: chim){ ans += 1LL * j.first * inversion_counter.get(j.second-1); inversion_counter.update(j.second, j.first); } for(pair<int, int> j: chim) inversion_counter.update(j.second, -j.first); cout << ans << "\n"; } cerr << "Time elapsed: " << clock() - start << " ms\n"; return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...