Submission #1113659

#TimeUsernameProblemLanguageResultExecution timeMemory
1113659vincentbucourt1Nile (IOI24_nile)C++17
38 / 100
99 ms21968 KiB
#include "nile.h" #include <bits/stdc++.h> using namespace std; #define ll long long // change int to ll struct Query { ll val, idx; }; bool cmpQuery (const Query& a, const Query& b) { return a.val < b.val; }; struct Edge { ll weight, u, v, type; }; bool cmpEdge (const Edge& a, const Edge& b) { if (a.weight < b.weight) { return true; } else if (a.weight > b.weight) { return false; } return a.type < b.type; } const ll INF = 1e18; ll N, Q; vector<ll> weight, solo, duo; vector<Query> queries; vector<Edge> edges; vector<ll> ans; struct DSU { vector<ll> info; ll cost; vector<ll> diffOdd, diffEven, allDuo; DSU (ll n) { info.assign(n, -1); diffOdd.resize(N), diffEven.resize(N), allDuo.resize(N); cost = 0; for (ll iVal = 0; iVal < N; iVal++) { cost += solo[iVal]; diffOdd[iVal] = solo[iVal] - duo[iVal]; diffEven[iVal] = INF; allDuo[iVal] = duo[iVal]; } } ll get (ll node) { return (info[node] < 0 ? node : info[node] = get(info[node])); } bool sameCC (ll u, ll v) { return get(u) == get(v); } ll sizeCC (ll u) { return -info[get(u)]; } ll getDiff (ll node) { node = get(node); ll ans = allDuo[node]; if (sizeCC(node) % 2 == 1) { ans += diffOdd[node]; } return ans; } bool merge (ll u, ll v) { ll initU = u, initV = v; u = get(u), v = get(v); if (abs(initU - initV) == 2) { assert(sameCC(u, v)); ll mid = min(initU, initV) + 1; cost -= diffOdd[u]; diffOdd[u] = min(diffOdd[u], solo[mid] - duo[mid]); diffEven[u] = min(diffEven[u], solo[mid] - duo[mid]); cost += diffOdd[u]; } if (u == v) return false; // assert(get(u) != get(v)); cost -= getDiff(u); cost -= getDiff(v); if (u > v) swap(u, v); if (sizeCC(u) % 2 == 1) { diffOdd[u] = min(diffOdd[u], diffEven[v]); diffEven[u] = min(diffEven[u], diffOdd[v]); } else { diffOdd[u] = min(diffOdd[u], diffOdd[v]); diffEven[u] = min(diffEven[u], diffEven[v]); } allDuo[u] += allDuo[v]; info[u] += info[v]; info[v] = u; cost += getDiff(u); // assert(get(v) == u); return true; } ll getCost () { return cost; } }; struct Pos { int idx, w, s, d; }; bool cmpOrder (const Pos& a, const Pos& b) { if (a.w < b.w) { return true; } else if (a.w > b.w) return false; return (a.s - a.d < b.s - b.d); } std::vector<long long> calculate_costs(std::vector<int> W, std::vector<int> A, std::vector<int> B, std::vector<int> E) { N = A.size(); Q = E.size(); weight.resize(N), solo.resize(N), duo.resize(N); vector<Pos> inp; inp.resize(N); queries.resize(Q); for (int i = 0; i < N; i++) { inp[i] = {i, W[i], A[i], B[i]}; } sort(inp.begin(), inp.end(), cmpOrder); for (int i = 0; i < N; i++) { weight[i] = inp[i].w; solo[i] = inp[i].s; duo[i] = inp[i].d; } for (ll iQuery = 0; iQuery < Q; iQuery++) { queries[iQuery] = {E[iQuery], iQuery}; } sort(queries.begin(), queries.end(), cmpQuery); for (ll iVal = 0; iVal < N-1; iVal++) { edges.push_back({weight[iVal+1] - weight[iVal], iVal, iVal+1, 1}); // assert(weight[iVal+1] - weight[iVal] >= 0); } for (ll iVal = 0; iVal < N-2; iVal++) { edges.push_back({weight[iVal+2] - weight[iVal], iVal, iVal+2, 2}); // assert(weight[iVal+2] - weight[iVal] >= 0); } sort(edges.begin(), edges.end(), cmpEdge); DSU dsu (N+1); ans.resize(Q); ll iEdge = 0; for (ll iQuery = 0; iQuery < Q; iQuery++) { ll qDiff = queries[iQuery].val; ll qIdx = queries[iQuery].idx; while (iEdge < (ll) (edges.size()) && edges[iEdge].weight <= qDiff) { dsu.merge(edges[iEdge].u, edges[iEdge].v); iEdge++; } ans[qIdx] = dsu.getCost(); } return ans; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...