Submission #84374

#TimeUsernameProblemLanguageResultExecution timeMemory
84374Alexa2001Construction of Highway (JOI18_construction)C++17
100 / 100
770 ms156840 KiB
#include <bits/stdc++.h> using namespace std; const int Nmax = 1e5 + 5; typedef long long ll; struct Val { int val, cnt; }; vector<int> v[Nmax]; vector<Val> A; int n, x[Nmax], y[Nmax], val[Nmax], t[Nmax]; struct AIB { int a[Nmax], n; int ub(int x) { return (x&(-x)); } void update(int pos, int val) { for(; pos; pos-=ub(pos)) a[pos] += val; } int query(int pos) { int ans = 0; for(; pos<=n; pos+=ub(pos)) ans += a[pos]; return ans; } void shrink(int n) { this->n = n; int i; for(i=0; i<=n; ++i) a[i] = 0; } } aib; namespace hld { static int where[Nmax], pos[Nmax], w[Nmax]; static vector<int> p[Nmax]; static deque<Val> z[Nmax]; void dfs(int node) { w[node] = 1; for(auto son : v[node]) { dfs(son); w[node] += w[son]; } } void prepare_chains(int node) { static int chains = 1; where[node] = chains; p[where[node]].push_back(node); pos[node] = p[where[node]].size(); if(v[node].empty()) return; int xson = v[node][0]; for(auto son : v[node]) if(w[son] > w[xson]) xson = son; prepare_chains(xson); for(auto son : v[node]) if(son != xson) { ++chains; prepare_chains(son); } } void path(int node, vector<Val> &A) { int s = 0, i, id = where[node], len = pos[node]; vector<Val> curr; for(i=0; i<z[id].size() && s + z[id][i].cnt <= len; ++i) { curr.push_back(z[id][i]); s += z[id][i].cnt; } if(i < z[id].size()) curr.push_back({ z[id][i].val, len - s }); reverse(curr.begin(), curr.end()); for(auto it : curr) A.push_back(it); if(id == 1) return; path(t[p[id][0]], A); } void update(int node, int val) { int id = where[node], len = pos[node]; while(z[id].size() && len >= z[id][0].cnt) len -= z[id][0].cnt, z[id].pop_front(); if(z[id].empty() && len == 1) /// this is the chain that includes the new node { z[id].push_back({val, pos[node]}); if(id == 1) return; update(t[p[id][0]], val); return; } /// otherwise the current chain is a "normal" one if(z[id].size()) z[id][0].cnt -= len; else assert(len == 0); z[id].push_front({val, pos[node]}); if(id == 1) return; update(t[p[id][0]], val); } }; ll solve(vector<Val> &A) /// count the number of inversions { reverse(A.begin(), A.end()); map<int,int> mp; for(auto it : A) mp[it.val] = 1; int cnt = 1; for(auto &it : mp) it.second = ++cnt; for(auto &it : A) it.val = mp[it.val]; aib.shrink(cnt); ll ans = 0; for(auto &it : A) { ans += (ll) aib.query(it.val + 1) * it.cnt; aib.update(it.val, it.cnt); } return ans; } int main() { // freopen("input", "r", stdin); cin.sync_with_stdio(false); int i; cin >> n; for(i=1; i<=n; ++i) cin >> val[i]; for(i=1; i<n; ++i) { cin >> x[i] >> y[i]; v[x[i]].push_back(y[i]); t[y[i]] = x[i]; } hld :: dfs(1); hld :: prepare_chains(1); hld :: z[1].push_back({val[1], 1}); for(i=1; i<n; ++i) { A.clear(); hld :: path(x[i], A); cout << solve(A) << '\n'; hld :: update(y[i], val[y[i]]); } return 0; }

Compilation message (stderr)

construction.cpp: In function 'void hld::path(int, std::vector<Val>&)':
construction.cpp:89:19: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         for(i=0; i<z[id].size() && s + z[id][i].cnt <= len; ++i)
                  ~^~~~~~~~~~~~~
construction.cpp:95:14: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         if(i < z[id].size())
            ~~^~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...