Submission #107766

#TimeUsernameProblemLanguageResultExecution timeMemory
107766hugo_pmWiring (IOI17_wiring)C++17
100 / 100
74 ms10704 KiB
#include "wiring.h" #include <bits/stdc++.h> using namespace std; #define form2(i, a, b) for (int i = (a); i < (b); ++i) #define ford2(i, a, b) for (int i = (a-1); i >= (b); --i) #define form(i, n) form2(i, 0, n) #define ford(i, n) ford2(i, n, 0) #define chmax(x, v) x = max(x, (v)) #define chmin(x, v) x = min(x, (v)) #define fi first #define se second #define vsz(x) (int)(x.size()) const long long BIG = 1000000000000000000LL; typedef long long ll; typedef long double ld; typedef pair<int, int> pii; int nbGroupes; vector<int> groupes; vector<int> beg; vector<int> rouges, bleus; vector<ll> redSom, blueSom; vector<vector<ll>> dp; void propag(int groupesProc, int restants, vector<int> &prevPos, vector<int> &curPos, vector<ll> &prevSom, vector<ll> &curSom) { //cout << groupesProc << " " << restants << " " << dp[groupesProc][restants] << endl << flush; assert(dp[groupesProc][restants] != BIG); int prev = groupesProc-1, cur = groupesProc; int relLeft = groupes[prev] - restants; assert(prevPos[beg[prev]] < curPos[beg[cur]]); assert(prevPos[beg[prev]+groupes[prev]-1] < curPos[beg[cur]]); // Transition 1 : prendre le plus à gauche des restants if (restants) { int relLeft = groupes[prev] - restants; int posLeft = prevPos[beg[prev] + relLeft]; int posAx = curPos[beg[cur]]; chmin(dp[groupesProc][restants-1], dp[groupesProc][restants] + posAx - posLeft); } // Transition 2 : prendre tous les restants, et les mettre avec nous if (restants > 0 && restants <= groupes[cur] && groupesProc < nbGroupes) { ll spCur = curSom[beg[cur] + restants] - curSom[beg[cur]]; ll spPrev = prevSom[beg[prev] + groupes[prev]] - prevSom[beg[prev] + relLeft]; assert(spCur > spPrev); chmin(dp[groupesProc+1][groupes[cur] - restants], dp[groupesProc][restants] + spCur - spPrev); } // Transition 3 : finir le groupe courant sur le groupe précédent, à la propagInit if (restants == 0) { chmin(dp[groupesProc+1][groupes[cur]], dp[groupesProc][0]); for (int now = groupes[cur]; now > 0; --now) { int lstPrev = prevPos[beg[prev] + groupes[prev]-1]; int posAx = curPos[beg[cur] + groupes[cur]-now]; chmin(dp[groupesProc+1][now-1], dp[groupesProc+1][now] + abs(lstPrev - posAx)); } } } void propagInit() { dp[1][groupes[0]] = 0; for (int now = groupes[0]; now > 0; --now) { chmin(dp[1][now-1], dp[1][now] + bleus[0] - rouges[groupes[0]-now]); } } void buildSom(vector<int> &pos, vector<ll> &som) { som.resize(pos.size() + 1U); som[0] = 0; form(i, vsz(pos)) { som[i+1] = som[i] + pos[i]; } } ll min_total_length(std::vector<int> r, std::vector<int> b) { if (r.front() > b.front()) swap(r, b); int n = r.size(), m = b.size(); int i = 0, j = 0; while (i < n && j < m) { groupes.push_back(0); if (r[i] < b[j]) { beg.push_back(i); while (i < n && r[i] < b[j]) { ++groupes.back(); ++i; } } else { beg.push_back(j); while (j < m && b[j] < r[i]) { ++groupes.back(); ++j; } } } if (i < n) { beg.push_back(i); groupes.push_back(n-i); } if (j < m) { beg.push_back(j); groupes.push_back(m-j); } rouges = r; bleus = b; nbGroupes = groupes.size(); buildSom(rouges, redSom); buildSom(bleus, blueSom); /*for (int x : groupes) cout << x << " "; cout << endl; for (int x : beg) cout << x << " "; cout << endl;*/ dp.resize(nbGroupes+1); form(i, nbGroupes) dp[i+1].assign(groupes[i]+1, BIG); propagInit(); form2(groupesProc, 1, nbGroupes) { ford(restants, groupes[groupesProc-1]+1) { if (groupesProc % 2 == 1) propag(groupesProc, restants, rouges, bleus, redSom, blueSom); else propag(groupesProc, restants, bleus, rouges, blueSom, redSom); } } return dp[nbGroupes][0]; }
#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...