Submission #1200674

#TimeUsernameProblemLanguageResultExecution timeMemory
1200674steveonalexWombats (IOI13_wombats)C++20
100 / 100
3603 ms169252 KiB
#include "wombats.h" #include <bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; #define MASK(i) (1ULL << (i)) #define GETBIT(mask, i) (((mask) >> (i)) & 1) #define ALL(v) (v).begin(), (v).end() ll max(ll a, ll b){return (a > b) ? a : b;} ll min(ll a, ll b){return (a < b) ? a : b;} ll gcd(ll a, ll b){return __gcd(a, b);} ll lcm(ll a, ll b){return a / gcd(a, b) * b;} ll LASTBIT(ll mask){return (mask) & (-mask);} int pop_cnt(ull mask){return __builtin_popcountll(mask);} int ctz(ull mask){return __builtin_ctzll(mask);} int logOf(ull mask){return 63 - __builtin_clzll(mask);} mt19937_64 rng(chrono::high_resolution_clock::now().time_since_epoch().count()); ll rngesus(ll l, ll r){return l + (ull) rng() % (r - l + 1);} double rngesus_d(double l, double r){ double wow = (double) ((ull) rng()) / ((ull)(0-1)); return wow * (r - l) + l; } template <class T1, class T2> bool maximize(T1 &a, T2 b){ if (a < b) {a = b; return true;} return false; } template <class T1, class T2> bool minimize(T1 &a, T2 b){ if (a > b) {a = b; return true;} return false; } template <class T> void printArr(T container, string separator = " ", string finish = "\n", ostream &out = cout){ for(auto item: container) out << item << separator; out << finish; } template <class T> void remove_dup(vector<T> &a){ sort(ALL(a)); a.resize(unique(ALL(a)) - a.begin()); } struct Slice{ vector<int> hori, verti; }; const int R = 5000, C = 200, INF = 1e9 + 69; struct Node{ int d[C][C]; Node(){ for(int i = 0; i < C; ++i) for(int j = 0; j < C; ++j) d[i][j] = INF; } }; const int BLOCK = 16; int r, c; int b_r; vector<Slice> a; Node produce_node(Slice x){ vector<int> pref = x.hori; pref.insert(pref.begin(), 0); for(int i = 1; i < (int) pref.size(); ++i) pref[i] += pref[i-1]; Node ans; for(int i = 0; i < c; ++i) for(int j = 0; j < c; ++j) { ans.d[i][j] = abs(pref[j] - pref[i]) + x.verti[j]; } return ans; } Node combine(Node x, Node y){ Node ans; int opt[c][c]; memset(opt, 0, sizeof opt); for(int i = c-1; i >= 0; --i) for(int j = 0; j < c; ++j){ int l = 0, r = c-1; if (i < c-1) r = opt[i+1][j]; if (j > 0) l = opt[i][j-1]; for(int k = l; k <= r; ++k){ if (minimize(ans.d[i][j], x.d[i][k] + y.d[k][j])) opt[i][j] = k; } } return ans; } struct SegmentTree{ int n; vector<Node> a; SegmentTree(){} SegmentTree(int _n, vector<Node> &b){ n = _n; a.resize(n * 2 + 2); build_tree(0, n-1, 1, b); } int choose_mid(int l,int r){ int j = logOf(r - l + 1); return min(l + MASK(j) - 1, r - MASK(j-1)); } void build_tree(int l, int r, int id, vector<Node> &b){ if (l == r){ a[id] = b[l]; return; } int mid = choose_mid(l, r); build_tree(l, mid, id * 2, b); build_tree(mid+1, r, id * 2 + 1, b); a[id] = combine(a[id * 2], a[id * 2 + 1]); } void update(int i, Node v, int l, int r, int id){ if (l == r){ a[id] = v; return; } int mid = choose_mid(l, r); if (i <= mid) update(i, v, l, mid, id * 2); else update(i, v, mid+1, r, id * 2 + 1); a[id] = combine(a[id * 2], a[id * 2 + 1]); } void update(int i, Node v){ update(i, v, 0, n-1, 1); } }; SegmentTree st; void init(int R, int C, int H[5000][200], int V[5000][200]) { r = R, c = C; for(int i = 0; i < r; ++i){ a.emplace_back(); a.back().hori.resize(c-1); a.back().verti.resize(c); for(int j = 0; j < c - 1; ++j) a.back().hori[j] = H[i][j]; if (i < r - 1){ for(int j = 0; j < c; ++j) a.back().verti[j] = V[i][j]; } } b_r = (r + BLOCK - 1) / BLOCK; vector<Node> b; for(int i = 0; i < b_r; ++i){ int L = i * BLOCK, R = min(r-1, (i+1) * BLOCK - 1); Node cur = produce_node(a[L]); for(int j = L+1; j <= R; ++j) cur = combine(cur, produce_node(a[j])); b.push_back(cur); } st = SegmentTree(b_r, b); } void changeH(int P, int Q, int W) { a[P].hori[Q] = W; int b_P = P / BLOCK; int L = b_P * BLOCK, R = min(r-1, (b_P + 1) * BLOCK - 1); Node b = produce_node(a[L]); for(int j = L+1; j <= R; ++j) b = combine(b, produce_node(a[j])); st.update(b_P, b); } void changeV(int P, int Q, int W) { a[P].verti[Q] = W; int b_P = P / BLOCK; int L = b_P * BLOCK, R = min(r-1, (b_P + 1) * BLOCK - 1); Node b = produce_node(a[L]); for(int j = L+1; j <= R; ++j) b = combine(b, produce_node(a[j])); st.update(b_P, b); } int escape(int V1, int V2) { return st.a[1].d[V1][V2]; }
#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...