Submission #1213336

#TimeUsernameProblemLanguageResultExecution timeMemory
1213336catch_me_if_you_canCats or Dogs (JOI18_catdog)C++20
100 / 100
262 ms27976 KiB
#include<bits/stdc++.h> #include "catdog.h" using namespace std; #define in array<int, 2> #define pb push_back #define pob pop_back #define fast() ios_base::sync_with_stdio(false); cin.tie(NULL) const int MX = 1e5+5; const int INF = 1e9; in col[3] = {{0, INF}, {INF, 0}, {0, 0}}; in contrib(in a) { return {min(a[0], a[1]+1), min(a[0]+1, a[1])}; } struct cdata { int v[2][2]; void init(in ab) { v[0][0] = ab[0]; v[1][1] = ab[1]; v[0][1] = v[1][0] = INF; return; } cdata operator+(const cdata &m) { cdata x; if((v[0][0] < 0)) return m; if((m.v[0][0] < 0)) { for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) x.v[i][j] = v[i][j]; return x; } for(int i = 0; i < 2; i++) { for(int j = 0; j < 2; j++) { x.v[i][j] = INF; for(int jp = 0; jp < 2; jp++) { for(int ip = 0; ip < 2; ip++) x.v[i][j] = min(x.v[i][j], v[i][jp] + m.v[ip][j] + (ip^jp)); } } } return x; } }; cdata cope; struct seg_tree { vector<cdata> tree; void init(int n) { tree.resize(4*n+13); for(auto &s: tree) s.init(col[2]); return; } void upd(in val, int p, int id, int l, int r) { if(l == r) { tree[id].init(val); return; } int m = (l+r)/2; if(p <= m) upd(val, p, 2*id, l, m); else upd(val, p, 2*id+1, m+1, r); tree[id] = tree[2*id] + tree[2*id+1]; return; } cdata query(int ql, int qr, int id, int l, int r) { if(qr < l || r < ql) return cope; if((ql <= l) && (r <= qr)) return tree[id]; int m = (l+r)/2; return query(ql, qr, 2*id, l, m) + query(ql, qr, 2*id+1, m+1, r); } }; int NN;// = n. seg_tree work; vector<int> temp;//serves no real purpose honestly, for convenience. vector<int> adj[MX]; vector<int> head(MX); vector<int> lv(MX); vector<int> pa(MX); vector<int> sub(MX); void dfs1(int u, int p) { sub[u] = 1; pa[u] = p; temp.clear(); for(int v: adj[u]) { if(v == p) continue; temp.pb(v); } swap(adj[u], temp); in bst = {-1, -1}; for(int s = 0; s < adj[u].size(); s++) { dfs1(adj[u][s], u); sub[u]+=sub[adj[u][s]]; bst = max(bst, {sub[adj[u][s]], s}); } if(bst[1] > 0) swap(adj[u][0], adj[u][bst[1]]); return; } int tin[MX]; int TIMER; void dfs2(int u) { tin[u] = ++TIMER; if(adj[u].empty()) { lv[u] = u; return; } head[adj[u][0]] = head[u]; dfs2(adj[u][0]); lv[u] = lv[adj[u][0]]; for(int v: adj[u]) { if(v == adj[u][0]) continue; head[v] = v; dfs2(v); } return; } vector<in> dp(MX);//current total contribution. it is really only important for the Heads. vector<in> light(MX);//current contribution from ONLY light children. we maintain this for everyone. vector<in> cur(MX);//current stuff. void initialize(int n, vector<int> a, vector<int> b) { NN = n; for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) cope.v[i][j] = -1; for(int i = 0; i < n-1; i++) { adj[a[i]].pb(b[i]); adj[b[i]].pb(a[i]); } for(int i = 1; i <= n; i++) { cur[i] = {0, 0}; light[i] = {0, 0}; dp[i] = {0, 0}; } dfs1(1, 0); head[1] = 1; TIMER = 0; dfs2(1); work.init(n); return; } int upd_light(int u, in LT) { int x = head[u]; light[u] = LT; work.upd(LT, tin[u], 1, 1, NN); cdata C = work.query(tin[x], tin[lv[u]], 1, 1, NN); in ndp = {min(C.v[0][0], C.v[0][1]), min(C.v[1][0], C.v[1][1])}; in noww = contrib(ndp); in earli = contrib(dp[x]); dp[x] = ndp;//correct the dp value int z = pa[x]; if(z == 0) return min(dp[x][0], dp[x][1]); in LTp;//we need to compute LTp LTp[0] = noww[0] - earli[0] + light[z][0]; LTp[1] = noww[1] - earli[1] + light[z][1]; return upd_light(z, LTp); } int upd(int u, in Lt) { in dlt = {Lt[0]-cur[u][0], Lt[1]-cur[u][1]}; cur[u] = Lt; in Ltp = {light[u][0] + dlt[0], light[u][1] + dlt[1]}; return upd_light(u, Ltp); } int cat(int v) { return upd(v, {0, INF}); } int dog(int v) { return upd(v, {INF, 0}); } int neighbor(int v) { return upd(v, {0, 0}); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...