Submission #1093952

#TimeUsernameProblemLanguageResultExecution timeMemory
1093952RequiemValley (BOI19_valley)C++17
100 / 100
199 ms90644 KiB
#include<bits/stdc++.h> #define int long long #define pb push_back #define fast ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); #define MOD 1000000007 #define inf 1000000000000000000 #define fi first #define se second #define FOR(i,a,b) for(int i=a;i<=b;i++) #define FORD(i,a,b) for(int i=a;i>=b;i--) #define sz(a) ((int)(a).size()) #define endl '\n' #define pi 3.14159265359 #define TASKNAME "valley" using namespace std; template<typename T> bool maximize(T &res, const T &val) { if (res < val){ res = val; return true; }; return false; } template<typename T> bool minimize(T &res, const T &val) { if (res > val){ res = val; return true; }; return false; } typedef pair<int,int> ii; typedef pair<int,ii> iii; typedef vector<int> vi; const int MAXN = 3e5 + 9; iii edge[MAXN]; int n, s, q, e; vector<int> shops; vector<ii> queries; int isShop[MAXN]; vector<int> g[MAXN]; array<int, 4> best[MAXN]; namespace subtask2{ bool check(){ return true; } int up[30][MAXN], down[30][MAXN], P[30][MAXN]; int depth[MAXN], dp[MAXN], dist[MAXN], in[MAXN], out[MAXN], timeDfs = 0; void update(array<int, 4> &res, int x){ FOR(i, 0, 3){ if (x < res[i]){ FORD(j, 3, i + 1){ res[j] = res[j - 1]; } res[i] = x; break; } } } int choose(array<int, 4> &res, vector<int> eliminate){ sort(eliminate.begin(), eliminate.end()); assert(eliminate.size() < 4); FOR(i, 0, 3){ if (i >= eliminate.size()) return res[i]; if (res[i] != eliminate[i]) return res[i]; } return 0; } inline int getDist(int u, int v){ return abs(dist[v] - dist[u]); } void init(){ function<void(int, int)> dfs = [&](int u, int p){ best[u] = {inf, inf, inf, inf}; in[u] = ++timeDfs; dp[u] = inf; if (isShop[u]) { minimize(dp[u], 0LL); update(best[u], 0LL); } for(int id: g[u]){ int v = edge[id].se.fi + edge[id].se.se - u; int w = edge[id].fi; if (v == p) continue; depth[v] = depth[u] + 1; dist[v] = dist[u] + w; dfs(v, u); minimize(dp[u], dp[v] + w); update(best[u], dp[v] + w); P[0][v] = u; } for(int id: g[u]){ int v = edge[id].se.fi + edge[id].se.se - u; int w = edge[id].fi; if (v == p) continue; up[0][v] = (isShop[v]) ? 0 : choose(best[u], {dp[v] + w}) + w; down[0][v] = min((isShop[v]) ? (w) : inf, choose(best[u], {dp[v] + w})); } out[u] = timeDfs; }; dfs(1, -1); P[0][1] = -1; up[0][1] = (isShop[1]) ? 0 : inf; down[0][1] = inf; // printf("\n"); // FOR(i, 1, n){ // printf("%lld ", down[0][i]); // } // printf("\n"); FOR(i, 1, 20){ FOR(j, 1, n){ if (P[i - 1][j] == -1) P[i][j] = -1; else P[i][j] = P[i - 1][P[i - 1][j]]; up[i][j] = down[i][j] = inf; if (P[i][j] != -1){ up[i][j] = min(up[i - 1][P[i - 1][j]] + getDist(P[i - 1][j], j), up[i - 1][j]); down[i][j] = min(down[i - 1][P[i - 1][j]], down[i - 1][j] + getDist(P[i - 1][j], P[i][j])); } // printf("%lld ", down[i][j]); } // printf("\n\n"); } } int getPath(int u, int v, bool Up){ //tu u den v va chieu cao can thiet d, Up: 1 trong 2 case. int cur, res; if (Up){ //di tu u len v res = inf; cur = u; FORD(i, 20, 0){ if (P[i][cur] != -1 and depth[P[i][cur]] >= depth[v]){ minimize(res, getDist(u, cur) + up[i][cur]); cur = P[i][cur]; } } } else{ //di xuong tu u xuong v cur = v; res = inf; FORD(i, 20, 0){ if (P[i][cur] != -1 and depth[P[i][cur]] >= depth[u]){ minimize(res, getDist(u, P[i][cur]) + down[i][cur]); cur = P[i][cur]; } } } return res; } int kthJump(int u, int k){ // cerr << u << ' ' << k << endl; if (k < 0 or k > depth[u]) return -1; FORD(i, 20, 0){ if (k & (1 << i)) u = P[i][u]; } return u; } int getLCA(int u, int v){ if (depth[u] < depth[v]) swap(u, v); FORD(i, 20, 0){ if (P[i][u] != -1 and depth[P[i][u]] >= depth[v]) u = P[i][u]; } if (u == v) return u; FORD(i, 20, 0){ if (P[i][u] != -1 and P[i][v] != -1 and P[i][u] != P[i][v]) u = P[i][u], v = P[i][v]; } return P[0][u]; } inline bool inSubtree(int u, int v){ //u co nam trong cay con goc v hay khong return in[u] >= in[v] and in[u] <= out[v]; } void solveQueries(){ FOR(i, 1, q){ int I, R; I = queries[i - 1].fi; R = queries[i - 1].se; int u = edge[I].se.fi; int v = edge[I].se.se; int w = edge[I].fi; if (depth[u] > depth[v]) swap(u, v); int res = inf; if ((inSubtree(R, v) ^ inSubtree(e, v)) == 0) { cout << "escaped\n"; } else{ if (isShop[R]) res = 0; if (inSubtree(R, v)){ minimize(res, getPath(R, v, 1)); minimize(res, choose(best[R], {})); } else if (inSubtree(R, u)){ int beforeR = kthJump(R, depth[R] - depth[u] - 1); if (beforeR != -1) minimize(res, getPath(R, beforeR, 1)); if (R != u) minimize(res, choose(best[R], {})); if (R == u) minimize(res, choose(best[u], {dp[v] + w})); else minimize(res, choose(best[u], {dp[v] + w, dp[beforeR] + getDist(beforeR, u)}) + getDist(R, u)); minimize(res, getPath(u, 1, 1) + getDist(R, u)); } else { int acs = getLCA(u, R); int beforeR = kthJump(R, depth[R] - depth[acs] - 1); int beforeU = kthJump(u, depth[u] - depth[acs] - 1); // printf("%lld %lld\n", R, acs); if (R == acs){ minimize(res, choose(best[R], {dp[beforeU] + dist[beforeU] - dist[R]})); minimize(res, getPath(R, u, 0)); minimize(res, choose(best[u], {dp[v] + w}) + getDist(R, u)); minimize(res, getPath(R, 1, 1)); } else{ minimize(res, getPath(R, beforeR, 1)); minimize(res, choose(best[R], {})); minimize(res, getDist(R, acs) + choose(best[acs],{dp[beforeU] + getDist(beforeU, acs), dp[beforeR] + getDist(beforeR, acs)})); minimize(res, getPath(acs, u, 0) + getDist(acs, R)); // printf("%lld %lld %lld %lld\n",res, acs, u, getPath(acs, u, 0)); minimize(res, choose(best[u], {dp[v] + w}) + getDist(acs, R) + getDist(acs, u)); minimize(res, getPath(acs, 1, 1) + getDist(R, acs)); } } if (res < inf) cout << res << endl; else cout << "oo\n"; } } } void solve(){ init(); solveQueries(); } } main() { fast; if (fopen(TASKNAME".inp","r")){ freopen(TASKNAME".inp","r",stdin); freopen(TASKNAME".out","w",stdout); } cin >> n >> s >> q >> e; FOR(i, 1, n - 1){ cin >> edge[i].se.fi >> edge[i].se.se >> edge[i].fi; g[edge[i].se.fi].pb(i); g[edge[i].se.se].pb(i); } FOR(i, 1, s){ int u; cin >> u; shops.pb(u); isShop[u] = 1; } FOR(i, 1, q){ int I, R; cin >> I >> R; queries.pb({I, R}); } if (subtask2::check()) return subtask2::solve(), 0; } /** Warning: - MLE / TLE? - Gioi han mang? - Gia tri max phai luon gan cho -INF - long long co can thiet khong? - tran mang. - code can than hon - Nho sinh test de tranh RTE / TLE --> Coi lai truoc khi nop **/

Compilation message (stderr)

valley.cpp: In function 'long long int subtask2::choose(std::array<long long int, 4>&, std::vector<long long int>)':
valley.cpp:56:19: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   56 |             if (i >= eliminate.size()) return res[i];
      |                 ~~^~~~~~~~~~~~~~~~~~~
valley.cpp: At global scope:
valley.cpp:244:1: warning: ISO C++ forbids declaration of 'main' with no type [-Wreturn-type]
  244 | main()
      | ^~~~
valley.cpp: In function 'int main()':
valley.cpp:248:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  248 |         freopen(TASKNAME".inp","r",stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
valley.cpp:249:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  249 |         freopen(TASKNAME".out","w",stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...