Submission #1200979

#TimeUsernameProblemLanguageResultExecution timeMemory
1200979MateiKing80Robots (APIO13_robots)C++20
0 / 100
1 ms320 KiB
#pragma GCC optimize("O3,unroll-loops") #include <iostream> #include <algorithm> #include <vector> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> #include <cassert> #pragma GCC target("avx2,bmi,bmi,popcnt,lzcnt") using namespace std; using namespace __gnu_pbds; #define all(x) (x).begin(), (x).end() using ll = long long; using ld = long double; //#define int ll using pii = pair<int, int>; #define fr first #define sc second const int N = 15e4 + 5, inf = 1e9 + 5; set<pii> av[8]; set<pii> taken[3][8]; int msks[N], xs[N], n; pair<int, ll> curr; void printAll(string message) { cout << message << '\n'; cout << "Curr: " << curr.fr << " " << curr.sc << '\n'; cout << "Av:\n"; for (int i = 0; i < 8; i ++) { cout << i << ": "; for (auto j : av[i]) cout << j.fr << " "; cout << '\n'; } cout << "Taken\n"; for (int k = 0; k < 3; k ++) { cout << "TakenK: " << k << '\n'; for (int i = 0; i < 8; i ++) { cout << i << ": "; for (auto j : taken[k][i]) cout << j.fr << " "; cout << '\n'; } } } bool add(int x) { int minn = inf; for (int i = 0; i < 8; i ++) if (i & (1 << x) && !av[i].empty() && minn > (*av[i].begin()).fr) minn = (*av[i].begin()).fr; for (int y = 0; y < 3; y ++) { if (x == y) continue; int costAdaug = inf; bool potSchimb = 0; for (int i = 0; i < 8; i ++) if (i & (1 << y) && !av[i].empty() && costAdaug > (*av[i].begin()).fr) costAdaug = (*av[i].begin()).fr; for (int i = 0; i < 8; i ++) if (i & (1 << y) && i & (1 << x) && !taken[y][i].empty()) potSchimb = 1; if (potSchimb) minn = min(minn, costAdaug); } for (int y = 0; y < 3; y ++) { if (x == y) continue; int z = 3 - x - y; int costAdaug = inf; bool potSchimbZY = 0; bool potSchimbYX = 0; for (int i = 0; i < 8; i ++) if (i & (1 << z) && !av[i].empty() && costAdaug > (*av[i].begin()).fr) costAdaug = (*av[i].begin()).fr; for (int i = 0; i < 8; i ++) if (i & (1 << z) && i & (1 << y) && !taken[z][i].empty()) potSchimbZY = 1; for (int i = 0; i < 8; i ++) if (i & (1 << y) && i & (1 << x) && !taken[y][i].empty()) potSchimbYX = 1; if (potSchimbYX && potSchimbZY) minn = min(minn, costAdaug); } if (minn >= inf) return false; curr.sc += minn; curr.fr ++; for (int i = 0; i < 8; i ++) if (i & (1 << x) && !av[i].empty() && minn == (*av[i].begin()).fr) { taken[x][i].insert(*av[i].begin()); av[i].erase(av[i].begin()); return true; } for (int y = 0; y < 3; y ++) { if (x == y) continue; int costAdaug = inf, deUnde = -1, ad = -1; bool potSchimb = 0; for (int i = 0; i < 8; i ++) if (i & (1 << y) && !av[i].empty() && costAdaug > (*av[i].begin()).fr) costAdaug = (*av[i].begin()).fr, ad = i; for (int i = 0; i < 8; i ++) if (i & (1 << y) && i & (1 << x) && !taken[y][i].empty()) potSchimb = 1, deUnde = i; if (potSchimb && costAdaug == minn) { pii sus = *taken[y][deUnde].begin(); taken[y][deUnde].erase(sus); taken[x][deUnde].insert(sus); sus = *av[ad].begin(); av[ad].erase(sus); taken[y][ad].insert(sus); return true; } } for (int y = 0; y < 3; y ++) { if (x == y) continue; int z = 3 - x - y; int costAdaug = inf, deUndeYX = -1, deUndeZY = -1, ad = -1; bool potSchimbZY = 0; bool potSchimbYX = 0; for (int i = 0; i < 8; i ++) if (i & (1 << z) && !av[i].empty() && costAdaug > (*av[i].begin()).fr) costAdaug = (*av[i].begin()).fr, ad = i; for (int i = 0; i < 8; i ++) if (i & (1 << z) && i & (1 << y) && !taken[z][i].empty()) potSchimbZY = 1, deUndeZY = i; for (int i = 0; i < 8; i ++) if (i & (1 << y) && i & (1 << x) && !taken[y][i].empty()) potSchimbYX = 1, deUndeYX = i; if (potSchimbYX && potSchimbZY && minn == costAdaug) { pii sus = *taken[z][deUndeZY].begin(); taken[z][deUndeZY].erase(sus); taken[y][deUndeZY].insert(sus); sus = *taken[y][deUndeYX].begin(); taken[y][deUndeYX].erase(sus); taken[x][deUndeYX].insert(sus); sus = *av[ad].begin(); av[ad].erase(sus); taken[z][ad].insert(sus); return true; } } assert(false); } bool rem(int x) { int maxx = -1; for (int i = 0; i < 8; i ++) if (i & (1 << x) && !taken[x][i].empty() && maxx < (*taken[x][i].rbegin()).fr) maxx = (*taken[x][i].rbegin()).fr; for (int y = 0; y < 3; y ++) { if (x == y) continue; int costScot = -1; bool potSchimb = 0; for (int i = 0; i < 8; i ++) if (i & (1 << y) && !taken[y][i].empty() && costScot < (*taken[y][i].rbegin()).fr) costScot = (*taken[y][i].rbegin()).fr; for (int i = 0; i < 8; i ++) if (i & (1 << y) && i & (1 << x) && !taken[x][i].empty()) potSchimb = 1; if (potSchimb) maxx = max(maxx, costScot); } for (int y = 0; y < 3; y ++) { if (x == y) continue; int z = 3 - x - y; int costScot = -1; bool potSchimbYZ = 0; bool potSchimbXY = 0; for (int i = 0; i < 8; i ++) if (i & (1 << z) && !taken[z][i].empty() && costScot < (*taken[z][i].rbegin()).fr) costScot = (*taken[z][i].rbegin()).fr; for (int i = 0; i < 8; i ++) if (i & (1 << y) && i & (1 << z) && !taken[y][i].empty()) potSchimbYZ = 1; for (int i = 0; i < 8; i ++) if (i & (1 << x) && i & (1 << y) && !taken[x][i].empty()) potSchimbXY = 1; if (potSchimbXY && potSchimbYZ) maxx = max(maxx, costScot); } if (maxx == -1) return false; //cout << "rem: " << maxx << '\n'; curr.sc -= maxx; curr.fr --; for (int i = 0; i < 8; i ++) if (i & (1 << x) && !taken[x][i].empty() && maxx == (*taken[x][i].rbegin()).fr) { av[i].insert(*taken[x][i].rbegin()); taken[x][i].erase(*taken[x][i].rbegin()); return true; } for (int y = 0; y < 3; y ++) { if (x == y) continue; int costScot = -1, ad = 0, deUnde = 0; bool potSchimb = 0; for (int i = 0; i < 8; i ++) if (i & (1 << y) && !taken[y][i].empty() && costScot < (*taken[y][i].rbegin()).fr) costScot = (*taken[y][i].rbegin()).fr, ad = i; for (int i = 0; i < 8; i ++) if (i & (1 << y) && i & (1 << x) && !taken[x][i].empty()) potSchimb = 1, deUnde = i; if (potSchimb && costScot == maxx) { pii sus = *taken[x][deUnde].rbegin(); taken[x][deUnde].erase(sus); taken[y][deUnde].insert(sus); sus = *taken[y][ad].rbegin(); av[ad].insert(sus); taken[y][ad].erase(sus); return true; } } for (int y = 0; y < 3; y ++) { if (x == y) continue; int z = 3 - x - y; int costScot = -1, ad = 0, deUndeXY = 0, deUndeYZ = 0; bool potSchimbYZ = 0; bool potSchimbXY = 0; for (int i = 0; i < 8; i ++) if (i & (1 << z) && !taken[z][i].empty() && costScot < (*taken[z][i].rbegin()).fr) costScot = (*taken[z][i].rbegin()).fr, ad = i; for (int i = 0; i < 8; i ++) if (i & (1 << y) && i & (1 << z) && !taken[y][i].empty()) potSchimbYZ = 1, deUndeYZ = i; for (int i = 0; i < 8; i ++) if (i & (1 << x) && i & (1 << y) && !taken[x][i].empty()) potSchimbXY = 1, deUndeXY = i; if (potSchimbXY && potSchimbYZ && costScot == maxx) { pii sus = *taken[y][deUndeYZ].rbegin(); taken[y][deUndeYZ].erase(sus); taken[z][deUndeYZ].insert(sus); sus = *taken[x][deUndeXY].rbegin(); taken[x][deUndeXY].erase(sus); taken[y][deUndeXY].insert(sus); sus = *taken[z][ad].rbegin(); av[ad].insert(sus); taken[z][ad].erase(sus); return true; } } assert(false); } bool add1() { if (!add(0)) { return false; } if (!add(1)) { rem(0); return false; } if (!add(1)) { rem(0); rem(1); return false; } if (!add(2)) { rem(0); rem(1); rem(1); return false; } return true; } bool add2() { if (!add(0)) { return false; } if (!add(1)) { rem(0); return false; } if (!add(2)) { rem(0); rem(1); return false; } if (!add(2)) { rem(0); rem(1); rem(2); return false; } return true; } bool remove1() { int sum1 = 0, sum2 = 0; for (int i = 0; i < 8; i ++) { sum1 += taken[1][i].size(); sum2 += taken[2][i].size(); } if (sum2 == 2 * sum1) return false; if (!rem(0)) { return false; } if (!rem(1)) { add(0); return false; } if (!rem(1)) { add(0); add(1); return false; } if (!rem(2)) { add(0); add(1); add(1); return false; } return true; } bool remove2() { int sum1 = 0, sum2 = 0; for (int i = 0; i < 8; i ++) { sum1 += taken[1][i].size(); sum2 += taken[2][i].size(); } if (2 * sum2 == sum1) return false; if (!rem(0)) { return false; } if (!rem(1)) { add(0); return false; } if (!rem(2)) { add(0); add(1); return false; } if (!rem(2)) { add(0); add(1); add(2); return false; } return true; } bool swap12() { if (!rem(1)) return false; if (!add(2)) { add(1); return false; } return true; } bool swap21() { if (!rem(2)) return false; if (!add(1)) { add(2); return false; } return true; } pair<int, ll> better(pair<int, ll> a, pair<int, ll> b) { if (a.fr > b.fr) return a; if (a.fr < b.fr) return b; if (a.sc < b.sc) return a; return b; } ll update(int pos, int val) { //ideea e ca se schimba putine chestii int sum1 = 0, sum2 = 0; for (int i = 0; i < 8; i ++) { sum1 += taken[1][i].size(); sum2 += taken[2][i].size(); } if (av[msks[pos]].count({xs[pos], pos})) { av[msks[pos]].erase({xs[pos], pos}); xs[pos] = val; av[msks[pos]].insert({xs[pos], pos}); } else { int loc = 0; if (taken[1][msks[pos]].count({xs[pos], pos})) loc = 1; if (taken[2][msks[pos]].count({xs[pos], pos})) loc = 2; if (2 * sum1 != sum2) { vector<int> f = {1, 2, 1}; f[loc] --; taken[loc][msks[pos]].erase({xs[pos], pos}); curr.fr --; curr.sc -= xs[pos]; for (int i = 0; i < 3; i ++) while (f[i] --) rem(i); xs[pos] = val; av[msks[pos]].insert({val, pos}); add1(); } else { vector<int> f = {1, 1, 2}; f[loc] --; taken[loc][msks[pos]].erase({xs[pos], pos}); curr.fr --; curr.sc -= xs[pos]; for (int i = 0; i < 3; i ++) while (f[i] --) rem(i); xs[pos] = val; av[msks[pos]].insert({val, pos}); add2(); } } if (remove1()) add1(); if (remove2()) add2(); pair<int, ll> ans = curr; if (swap12()) { if (better(ans, curr) == ans) swap21(); ans = curr; } if (swap21()) { if (better(ans, curr) == ans) swap12(); ans = curr; } return ans.sc; } pair<int, ll> solve() { for (int i = 0; i < n; i ++) av[msks[i]].insert({xs[i], i}); pair<int, ll> ans = {0, 0}; curr = {0, 0}; while (1) { ans = better(ans, curr); if (!add1()) break; } while (1) { ans = better(ans, curr); if (add2()) continue; if (swap12()) continue; break; } for (int i = 0; i < 8; i ++) { av[i].clear(); for (int j = 0; j < 3; j ++) taken[j][i].clear(); } for (int i = 0; i < n; i ++) av[msks[i]].insert({xs[i], i}); curr = {0, 0}; while (1) { if (ans == curr) break; if (!add1()) break; } while (1) { if (ans == curr) break; if (add2()) continue; if (swap12()) continue; break; } return {ans.fr / 4, ans.sc}; } signed main() { ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n; for (int i = 0; i < n; i ++) { int msk, x; cin >> msk >> x; int sus = 0; if (msk >= 100) { msk -= 100; sus ++; } if (msk >= 10) { msk -= 10; sus += 2; } if (msk) { msk --; sus += 4; } msks[i] = sus; xs[i] = x; } pair<int, ll> ans = solve(); cout << ans.fr << " " << ans.sc << '\n'; int q; cin >> q; while (q --) { int x, y; cin >> x >> y; ll sus = update(x - 1, y); cout << sus << '\n'; } } /* fac o chestie de genu fac for prin numarul de echipe <- cred ca e usor calculabil apoi fixez numarul de echipe cu 2 matematicieni daca calculez corect numarul ce se intampla pentru asta, ca sa pot schimba un matematician la informatician am mai multe variante: iau cel mai ieftin informatician de pe bara { dau afara un matematician SAU transform un matematician in ciucuiala, ciucuiala e dat afara } SAU { transform un matematician in informatician transform un ciucuiala in informatician { iau un ciucuiala de pe bara si dau afara un matematician transform un matematician in ciucuiala } } -> merge pentru Q = 0, 53 pct, mai mult ca suficient acuma numarul de echipe cum il fac :/ fac greeeeeeeeedy imi fac prima data o echipa apoi inca una sinca una ... ideea e ca eu o sa am nevoie de update-uri de tipul: scoate X optim baga X optim scoate e usor, scoti al mai ieftin -> fals la baga X : { bagi cel mai ieftin X de pe bara bagi Y, schimbi Y in X bagi Z, schimbi Z in Y, schimbi Y in X } la scoate X : { scoti cel mai scump X scoti Y, schimbi X in Y scoti Z, schimbi X in Y, schimbi Y in Z } -> daca asta e corect, nu cred ca e atat de deep am nevoie acum sa fac subtask-ul 2 nr de echipe */
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...