Submission #53143

#TimeUsernameProblemLanguageResultExecution timeMemory
53143FLDutchmanWiring (IOI17_wiring)C++14
100 / 100
170 ms96900 KiB
#include "wiring.h" #include <bits/stdc++.h> using namespace std; typedef vector<int> VI; #define int long long #define pb push_back #define snd second #define fst first #define FOR(i, l, r) for(int i = (l); i < (r); i++) typedef vector<int> vi; typedef pair<int, int> ii; typedef vector<ii> vii; const int NMAX = 2e5+10; const int INF = 1e18+10; int N = 0, C = 0; vi color, pos; vi size, dist; vii comps; vi le[NMAX], ri[NMAX], v[NMAX]; vi dp[NMAX]; // min segtree struct segTree{ int size; vi tree, lazy; segTree(vi &arr){ size = arr.size(); tree.assign(4*size, 0); lazy.assign(4*size, 0); buildTree(arr, 0, size, 1); } void buildTree(vi &arr, int lb, int rb, int n){ if(lb+1==rb) { tree[n] = arr[lb]; return; } int mb = (lb+rb)/2; buildTree(arr, lb, mb, 2*n); buildTree(arr, mb, rb, 2*n+1); tree[n] = min(tree[2*n], tree[2*n+1]); } void recAdd(int v, int l, int r, int lb, int rb, int n){ //cout << "recAdd " << v << " " << l << " " << r << " " << lb << " " << rb << " " << n << endl; if(l <= lb and rb <= r){ tree[n] += v; lazy[n] += v; return; } int mb = (lb+rb)/2; if(lazy[n]){ recAdd(lazy[n], lb, rb, lb, mb, 2*n); recAdd(lazy[n], lb, rb, mb, rb, 2*n+1); lazy[n] = 0; } if(l < mb) recAdd(v, l, r, lb, mb, 2*n); if(r > mb) recAdd(v, l, r, mb, rb, 2*n+1); tree[n] = min(tree[2*n], tree[2*n+1]); } int zero(int rb, int n=1){ if(rb == 1) return tree[n]; int mb = rb/2; if(lazy[n]){ recAdd(lazy[n], 0, rb, 0, mb, 2*n); recAdd(lazy[n], 0, rb, mb, rb, 2*n+1); lazy[n] = 0; } return zero(mb, 2*n); } int zero(){ return zero(size); } void add(int v, int l){ recAdd(v, l, size, 0, size, 1); } int mq(){ return tree[1]; } }; long long min_total_length(VI r, VI b) { N = r.size() + b.size(); int i = 0, j = 0; r.pb(1e9+10); b.pb(1e9+10); while(i + j < N){ //cout << i << " " << j << endl; if(r[i] < b[j]) { pos.pb(r[i++]); color.pb(0); } else { pos.pb(b[j++]); color.pb(1); } } int start = 0; //cout << "Built pos" << endl; FOR(i, 1, N){ if(color[i-1] != color[i]){ comps.pb({start, i-1}); size.pb(i-start); start = i; } } comps.pb({start, N-1}); size.pb(N-start); C = comps.size(); //cout << "Built comps" << endl; FOR(i, 0, C){ //cout << i << endl; int s = size[i]; le[i].assign(s+1, 0); ri[i].assign(s+1, 0); // leftmost, rightmost int l = pos[comps[i].fst], r = pos[comps[i].snd]; FOR(j, 1, s+1) le[i][j] = le[i][j-1] + pos[comps[i].fst + j-1] - l; for(int j = s-1; j >= 0; j--) ri[i][j] = ri[i][j+1] + r - pos[comps[i].fst + j]; } //dp[i][k] => min wire needed to connect comp i onwards, given that k wires are coming in from the left dist.assign(C, 0); dist[0] = INF; FOR(i, 1, C) dist[i] = pos[comps[i].fst] - pos[comps[i-1].snd]; FOR(i, 0, C) FOR(j, 0, le[i].size()) v[i].pb(le[i][j] + ri[i][j]); dp[C].pb(0); dp[C].pb(INF); for(int i = C-1; i >= 0; i--){ //cout << "i = " << i << endl; // dp[C] vi arr(size[i]+1, 0); dp[i].assign(size[i]+1, INF); FOR(j, 0, size[i]+1) { arr[j] = v[i][j] + dp[i+1][ min(size[i] - j, (int) dp[i+1].size() -1 ) ]; if(i != C and size[i]-j > (int)dp[i+1].size()-1){ arr[j] += dist[i+1] * (size[i]-j - (int) dp[i+1].size()+1); } } //cout << "Made array" << endl; segTree t(arr); //cout << "Built tree" << endl; int extra = size[i] * dist[i]; dp[i][size[i]] = t.mq() + extra; for(int k = size[i]-1; k >= 0; k--){ //cout << "k = " <<k<<endl; t.add(dist[i], k+1); //cout << "added" << endl; extra -= dist[i]; dp[i][k] = t.mq() + extra; if(i == 0) dp[i][k] = t.zero(); } } /* cout << "pos: \t\t"; for(int k : pos) cout << k << " "; cout << endl; cout << "color: \t\t"; for(int k : color) cout << k << " "; cout << endl; cout << "comps: \t\t"; for(ii k : comps) cout << k.fst << " " << k.snd << "\t"; cout << endl; cout << "dist: \t\t"; for(int k : dist) cout << k << " "; cout << endl; cout << "left: \n"; FOR(i, 0, C) { for(int k : le[i]) cout << k << " "; cout << endl; } cout << "right: \n"; FOR(i, 0, C) { for(int k : ri[i]) cout << k << " "; cout << endl; } cout << "v: \n"; FOR(i, 0, C) { for(int k : v[i]) cout << k << " "; cout << endl; } segTree t(pos); t.add(-9, 5); cout << t.mq() << endl; cout << "dp: \n"; FOR(i, 0, C+1) { for(int k : dp[i]) cout << k << " "; cout << endl; } */ return dp[0][0]; } /* 4 5 1 2 3 7 0 4 5 9 10 5 3 1 3 9 102 103 5 125 130 */

Compilation message (stderr)

wiring.cpp: In function 'long long int min_total_length(VI, VI)':
wiring.cpp:11:41: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 #define FOR(i, l, r) for(int i = (l); i < (r); i++)
                                         ^
wiring.cpp:137:15: note: in expansion of macro 'FOR'
  FOR(i, 0, C) FOR(j, 0, le[i].size()) v[i].pb(le[i][j] + ri[i][j]);
               ^~~
#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...