Submission #552721

#TimeUsernameProblemLanguageResultExecution timeMemory
552721MagiSwapping Cities (APIO20_swap)C++14
100 / 100
683 ms57124 KiB
#include "swap.h" #include <iostream> #include <vector> #include <algorithm> #define f first #define s second using namespace std; const int NMAX = 1e5, MMAX = 2e5, inf = 2e9; int n, m, tata[NMAX+10], rang[NMAX+10], mini[3][NMAX+10], costTata[NMAX+10], dp[20][NMAX+10], dp1[20][NMAX+10], dp2[20][NMAX+10], nivel[NMAX+10]; int dp_sus[NMAX+10], dpCycle[NMAX+10]; pair <int, int> dp_jos[2][NMAX+10]; vector <pair <int, int> > nod[NMAX+10], tree[NMAX+10]; struct Kruskal{ int n1, n2, cost; }K[MMAX+10]; inline bool cmp(Kruskal a, Kruskal b){ return a.cost < b.cost; } int findDaddy(int x){ int r = x, y = x; while(r != tata[r]) r = tata[r]; while(x != tata[x]){ y = tata[x]; tata[x] = r; x = y; } return r; } void unite(int x, int y){ if(rang[x] < rang[y]) tata[x] = y; else tata[y] = x; if(rang[x] == rang[y]) rang[x]++; } void dfs(int x, int p = 0){ dp[0][x] = p; nivel[x] = nivel[p] + 1; for(auto u : nod[x]) if(u.f != p){ for(int t=0; t<3; t++) if(mini[t][x] > u.s){ for(int t1=2; t1>t; t1--) mini[t1][x] = mini[t1-1][x]; mini[t][x] = u.s; break; } } for(auto u : tree[x]) if(u.f != p){ dfs(u.f, x); costTata[u.f] = u.s; } } void dfs1(int x, int p = 0){ dp_jos[0][x].f = dp_jos[0][x].s = dp_jos[1][x].f = dp_jos[1][x].s = inf; dpCycle[x] = inf; for(auto u : nod[x]) if(dp[0][u.f] != x && dp[0][x] != u.f) dpCycle[x] = min(dpCycle[x], u.s); for(auto u : tree[x]) if(u.f != p){ dfs1(u.f, x); if(max(u.s, min(dp_jos[0][u.f].f, mini[1][u.f])) < dp_jos[0][x].f){ dp_jos[1][x] = dp_jos[0][x]; dp_jos[0][x] = {max(u.s, min(dp_jos[0][u.f].f, mini[1][u.f])), u.s}; } else if(max(u.s, min(dp_jos[0][u.f].f, mini[1][u.f])) < dp_jos[1][x].f){ dp_jos[1][x] = {max(u.s, min(dp_jos[0][u.f].f, mini[1][u.f])), u.s}; } dpCycle[x] = min(dpCycle[x], max(u.s, dpCycle[u.f])); } } void dfs2(int x, int p = 0){ dp_sus[x] = min(min(mini[2][x], max(mini[1][x], costTata[x])), max(costTata[x], dp_sus[dp[0][x]])); if(dp_jos[0][dp[0][x]].s == x) dp_sus[x] = min(dp_sus[x], max(costTata[x], dp_jos[1][dp[0][x]].f)); else dp_sus[x] = min(dp_sus[x], max(costTata[x], dp_jos[0][dp[0][x]].f)); for(auto u : tree[x]) if(u.f != p) dfs2(u.f, x); } void buildStramosi(){ for(int i=1; i<=n; i++){ if(costTata[i] != mini[0][dp[0][i]]) dp2[0][i] = mini[0][dp[0][i]]; else dp2[0][i] = mini[1][dp[0][i]]; dp1[0][i] = costTata[i]; } for(int bit=1; (1<<bit)<=n; bit++) for(int i=1; i<=n; i++){ dp[bit][i] = dp[bit-1][dp[bit-1][i]]; dp1[bit][i] = max(dp1[bit-1][i], dp1[bit-1][dp[bit-1][i]]); dp2[bit][i] = min(dp2[bit-1][i], dp2[bit-1][dp[bit-1][i]]); } } pair <int, int> lca(int x, int y){ if(nivel[x] < nivel[y]) swap(x, y); int dif = nivel[x] - nivel[y], ans = 0; for(int bit=0; (1<<bit)<=dif; bit++) if(dif & (1 << bit)){ ans = max(ans, dp1[bit][x]); x = dp[bit][x]; } if(x == y) return {x, ans}; for(int bit=19; bit>=0; bit--) if(dp[bit][x] != dp[bit][y]){ ans = max(ans, max(dp1[bit][x], dp1[bit][y])); x = dp[bit][x]; y = dp[bit][y]; } return {dp[0][x], max(ans, max(dp1[0][x], dp1[0][y]))}; } int findStr(int x, int k){ for(int bit=0; (1<<bit)<=k; bit++) if(k & (1 << bit)) x = dp[bit][x]; return x; } int minLant(int x, int k){ int ans = inf; for(int bit=0; (1<<bit)<=k; bit++) if(k & (1 << bit)){ ans = min(ans, dp2[bit][x]); x = dp[bit][x]; } return ans; } void init(int N, int M, std::vector<int> U, std::vector<int> V, std::vector<int> W){ n = N; m = M; for(int i=1; i<=n; i++) tata[i] = i, rang[i] = 1; for(int i=0; i<m; i++){ int nod1 = U[i] + 1, nod2 = V[i] + 1, cost = W[i]; nod[nod1].push_back({nod2, cost}); nod[nod2].push_back({nod1, cost}); K[i+1] = {nod1, nod2, cost}; } sort(K+1, K+m+1, cmp); for(int i=1; i<=m; i++){ int val1 = findDaddy(K[i].n1), val2 = findDaddy(K[i].n2); if(val1 != val2){ unite(val1, val2); tree[K[i].n1].push_back({K[i].n2, K[i].cost}); tree[K[i].n2].push_back({K[i].n1, K[i].cost}); } } for(int i=1; i<=n; i++) mini[0][i] = mini[1][i] = mini[2][i] = inf; costTata[1] = inf; dfs(1); dfs1(1); dfs2(1); buildStramosi(); } int getMinimumFuelCapacity(int X, int Y){ int x = X + 1, y = Y + 1; pair <int, int> LCA = lca(x, y); int val1 = LCA.s, val2 = inf; if(findStr(y, nivel[y] - nivel[LCA.f]) == x) swap(x, y); if(findStr(x, nivel[x] - nivel[LCA.f]) == y){ val2 = mini[1][x]; int val = nivel[x] - nivel[LCA.f] - 1, str = findStr(x, val); val2 = min(val2, minLant(x, val)); val2 = min(val2, dp_sus[str]); val2 = min(val2, dpCycle[y]); } else{ val2 = min(dp_jos[0][x].f, dp_jos[0][y].f); val2 = min(val2, min(mini[1][x], mini[1][y])); int val = nivel[x] - nivel[LCA.f] - 1; val2 = min(val2, minLant(x, val)); val = nivel[y] - nivel[LCA.f] - 1; val2 = min(val2, minLant(y, val)); val2 = min(val2, min(mini[2][LCA.f], costTata[LCA.f])); val2 = min(val2, dpCycle[x]); val2 = min(val2, dpCycle[y]); } if(val2 == inf) return -1; return max(val1, val2); }
#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...