Submission #798433

#TimeUsernameProblemLanguageResultExecution timeMemory
798433hugo_pmWild Boar (JOI18_wild_boar)C++17
100 / 100
15781 ms685616 KiB
#include <bits/stdc++.h> #define int long long using namespace std; #define all(v) (v).begin(), (v).end() #define rall(v) (v).rbegin(), (v).rend() #define rep(i, a, b) for(int i = (a); i < (b); i++) #define sz(v) ((int)((v).size())) template<typename T> void chmax(T &x, const T &v) { if (x < v) x = v; } template<typename T> void chmin(T &x, const T &v) { if (x > v) x = v; } using pii = pair<int, int>; using vi = vector<int>; string to_string(string s) { return s; } template <typename T> string to_string(T v) { bool first = true; string res = "["; for (const auto &x : v) { if (!first) res += ", "; first = false; res += to_string(x); } res += "]"; return res; } template <typename A, typename B> string to_string(pair<A, B> p) { return "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; } void dbg_out() { cout << endl; } template <typename Head, typename... Tail> void dbg_out(Head H, Tail... T) { cout << ' ' << to_string(H); dbg_out(T...); } #ifdef DEBUG #define dbg(...) cout << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__) #else #define dbg(...) #endif const int MAX_N = 2005, MAX_ARRET = 1 << 17; int nbNode, nbEdge, nbReq, nbArret; vector<int> adj[MAX_N]; int xorNode[MAX_N]; int poids[MAX_N]; int arrets[MAX_ARRET]; int vus[MAX_N][MAX_N]; int VuTime = 0; struct Chemin { int len, fst, lst; bool operator<(const Chemin &oth) const { return tie(len, fst, lst) < tie(oth.len, oth.fst, oth.lst); } bool operator==(const Chemin &oth) const { return tie(len, fst, lst) == tie(oth.len, oth.fst, oth.lst); } }; template<typename T> using minpq = priority_queue<T, vector<T>, greater<T>>; string to_string(const Chemin c) { return "(len=" + to_string(c.len) + ", fst=" + to_string(c.fst) + ", lst=" + to_string(c.lst) + ")"; } int cntFirst[MAX_N + 1], cntLast[MAX_N + 1]; vector<Chemin> compressTab (vector<Chemin> &chemins) { #ifdef DEBUG assert(is_sorted(all(chemins))); #endif VuTime++; vector<Chemin> ret; for (Chemin chem : chemins) { if (ret.size() > 8) break; dbg(chem); if (cntFirst[1+chem.fst] == 3 or cntLast[1+chem.lst] == 3 or vus[1+chem.fst][1+chem.lst] == VuTime) continue; ret.push_back(chem); cntFirst[1+chem.fst]++; cntLast[1+chem.lst]++; vus[1+chem.fst][1+chem.lst] = VuTime; } for (Chemin chem : ret) { cntFirst[1+chem.fst]--; cntLast[1+chem.lst]--; } return ret; }; /// i-eme feuille = candidats pour X[i] -> X[i+1] vector<Chemin> tree[2*MAX_ARRET]; const int sizeTree = MAX_ARRET; vector<Chemin> merge(const vector<Chemin> &v1, const vector<Chemin> &v2) { vector<Chemin> nv; for (const Chemin &c1 : v1) for (const Chemin &c2 : v2) { if (c1.lst != c2.fst) { int newFst = (c1.fst == -1 ? c2.fst : c1.fst); nv.push_back({c1.len + c2.len, newFst, c2.lst}); } } sort(all(nv)); return compressTab(nv); } int leftRightLeaf(int idx) { if (idx < sizeTree) idx = 2*idx+1; while (idx < sizeTree) idx *= 2; return idx - sizeTree; } void _recalc(int idx) { if (leftRightLeaf(idx) >= nbArret-1) { // todo check tree[idx] = tree[2*idx]; } else { tree[idx] = merge(tree[2*idx], tree[2*idx+1]); } } void buildTree() { for (int node = sizeTree-1; node >= 1; --node) { _recalc(node); } } void update(int idx, vector<Chemin> v) { idx += sizeTree; tree[idx] = v; int lvl = 0; while (idx > 1) { idx /= 2; if (((2*idx+1) << lvl) - sizeTree >= nbArret-1) { // todo check tree[idx] = tree[2*idx]; } else { tree[idx] = merge(tree[2*idx], tree[2*idx+1]); } ++lvl; } } vector<Chemin> matrice[MAX_N][MAX_N]; void buildMatrice() { auto interesting = [&] (const Chemin &add, vector<Chemin> &V) { V.insert(upper_bound(all(V), add), add); V = compressTab(V); return (find(all(V), add) != end(V)); }; rep(depart, 0, nbNode) { auto& cand = matrice[depart]; cand[depart].push_back({0, -1, -1}); minpq<pair<Chemin, int>> pq; pq.push({cand[depart].back(), depart}); vector<int> nbVus(nbNode); while (!pq.empty()) { auto [oldChemin, node] = pq.top(); pq.pop(); nbVus[node]++; // oldChemin.len == dist[node] dbg(depart, node); if (find(all(cand[node]), oldChemin) == end(cand[node])) { continue; } for (int iEdge : adj[node]) { if (iEdge == oldChemin.lst) continue; int voisin = xorNode[iEdge]^node; Chemin nouvChemin { oldChemin.len + poids[iEdge], (oldChemin.fst == -1 ? iEdge : oldChemin.fst), iEdge }; if (interesting(nouvChemin, cand[voisin])) { dbg(voisin, cand[voisin], nouvChemin); pq.push({nouvChemin, voisin}); } } } rep(node, 0, nbNode) { cand[node] = compressTab(cand[node]); assert(sz(cand[node]) <= 9); } } } signed main() { ios::sync_with_stdio(false); cin.tie(0); cin >> nbNode >> nbEdge >> nbReq >> nbArret; rep(iEdge, 0, nbEdge) { int u, v; cin >> u >> v; --u, --v; cin >> poids[iEdge]; xorNode[iEdge] = u^v; adj[u].push_back(iEdge); adj[v].push_back(iEdge); } buildMatrice(); rep(iArret, 0, nbArret) { cin >> arrets[iArret]; --arrets[iArret]; if (iArret > 0) { tree[sizeTree + iArret-1] = matrice[arrets[iArret-1]][arrets[iArret]]; } } buildTree(); rep(iReq, 0, nbReq) { int indice, val; cin >> indice >> val; --indice, --val; arrets[indice] = val; if (indice > 0) { update(indice-1, matrice[arrets[indice-1]][arrets[indice]]); } if (indice+1 < nbArret) { update(indice, matrice[arrets[indice]][arrets[indice+1]]); } int ans = -1; if (!tree[1].empty()) ans = tree[1].front().len; cout << ans << '\n'; } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...