Submission #707309

#TimeUsernameProblemLanguageResultExecution timeMemory
707309Nhoksocqt1Tropical Garden (IOI11_garden)C++17
69 / 100
348 ms60976 KiB
#include<bits/stdc++.h> #include "garden.h" #include "gardenlib.h" using namespace std; #define inf 0x3f3f3f3f #pragma GCC target ("avx2") #pragma GCC optimization ("O3") #pragma GCC optimization ("unroll-loops") #define sz(x) int((x).size()) #define fi first #define se second typedef long long ll; typedef pair<int, int> ii; template<class X, class Y> inline bool maximize(X &x, const Y &y) {return (x < y ? x = y, 1 : 0);} template<class X, class Y> inline bool minimize(X &x, const Y &y) {return (x > y ? x = y, 1 : 0);} mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); int Random(int l, int r) { return uniform_int_distribution<int>(l, r)(rng); } const int MAXN = 150005; const int MAXM = 300005; struct Edge { int u, v; } edge[MAXN]; struct Query { int K, pos; } qr[2005]; vector<ii> adj[MAXN], B[MAXM]; vector<int> adjp[MAXM], C[MAXM], comp[MAXM]; int h[MAXM], timeIn[MAXM], timeOut[MAXM], result[2005]; int firstToLoop[MAXM], firstInLoop[MAXM], loopOf[MAXM], posInComp[MAXM]; int deg[MAXM], pa[MAXM], idc[MAXM], idn[MAXN], numNode, numEdge, numQuery, lastNode; bool dx[MAXM], ok[MAXM]; inline int getLeftNode(int id) { return (id >= numEdge) ? edge[id - numEdge].v : edge[id].u; } int timeIn0; void preDfs(int u, int p) { timeIn[u] = ++timeIn0; for (int it = 0; it < int(adjp[u].size()); ++it) { int v(adjp[u][it]); if(v != p) { h[v] = 1 + h[u]; preDfs(v, u); } } timeOut[u] = timeIn0; } void dfsLast(int u, int p) { dx[u] = 1; for (int it = 0; it < int(adjp[u].size()); ++it) { int v(adjp[u][it]); if(v != p) { dfsLast(v, u); } } while(B[u].size()) { C[h[u] - B[u].back().fi].push_back(B[u].back().se); B[u].pop_back(); } while(C[h[u]].size()) { if(adjp[u].size() > 0 && getLeftNode(u) == lastNode) ++result[C[h[u]].back()]; C[h[u]].pop_back(); } } void count_routes(int _N, int _M, int _P, int _R[][2], int _Q, int _G[]) { numNode = _N, numEdge = _M, lastNode = _P, numQuery = _Q; for (int i = 0; i < _M; ++i) { int u(_R[i][0]), v(_R[i][1]); edge[i] = {u, v}; adj[u].push_back({v, i}); adj[v].push_back({u, i}); } for (int u = 0; u < numNode; ++u) { int id0 = adj[u][0].se; int id1 = (adj[u].size() > 1 ? adj[u][1].se : 1e9+7); bool type0 = (u == edge[adj[u][0].se].v); bool type1 = (adj[u].size() > 1 && (u == edge[adj[u][1].se].v)); for (int it = 0; it < int(adj[u].size()); ++it) { int v(adj[u][it].fi), id(adj[u][it].se); bool type = !(u == edge[id].v); if(it == 0) { idn[u] = id + !type * numEdge; ok[idn[u]] = 1; } pa[id + type * numEdge] = (id != id0 || id1 >= 1e9+7) ? id0 + type0 * numEdge : id1 + type1 * numEdge; ++deg[pa[id + type * numEdge]]; } } int numComp(0); for (int id = 0; id < 2 * numEdge; ++id) { if(deg[id] || dx[id]) continue; vector<int> tmpn; int tmp(id); while(!dx[tmp]) { dx[tmp] = 1; tmpn.push_back(tmp); tmp = pa[tmp]; } int szn(tmpn.size()); for (int it = 0; it <= szn; ++it) { if(it == szn || tmpn[it] == tmp) { if(it < szn) { for (int jt = it; jt < szn; ++jt) { posInComp[tmpn[jt]] = jt - it; comp[numComp].push_back(tmpn[jt]); firstInLoop[tmpn[jt]] = tmpn[jt]; loopOf[tmpn[jt]] = szn - it; firstToLoop[tmpn[jt]] = 0; idc[tmpn[jt]] = numComp; } ++numComp; } if(it > 0) { adjp[tmp].push_back(tmpn[it - 1]); for (int jt = 0; jt < it; ++jt) { posInComp[tmpn[jt]] = jt; comp[numComp].push_back(tmpn[jt]); firstToLoop[tmpn[jt]] = it - jt + firstToLoop[tmp]; firstInLoop[tmpn[jt]] = firstInLoop[tmp]; idc[tmpn[jt]] = numComp; if(jt + 1 < it) adjp[tmpn[jt + 1]].push_back(tmpn[jt]); } ++numComp; } break; } } } for (int id = 0; id < 2 * numEdge; ++id) { if(!deg[id] || dx[id]) continue; int tmp(id); while(!dx[tmp]) { dx[tmp] = 1; posInComp[tmp] = comp[numComp].size(); comp[numComp].push_back(tmp); idc[tmp] = numComp; firstToLoop[tmp] = 0; firstInLoop[tmp] = tmp; tmp = pa[tmp]; } int szn(comp[numComp].size()); for (int it = 0; it < szn; ++it) loopOf[comp[numComp][it]] = szn; ++numComp; } for (int id = 0; id < 2 * numEdge; ++id) { if(!timeIn[id]) preDfs(id, -1); } for (int t = 0; t < numQuery; ++t) qr[t] = {_G[t], t}; sort(qr, qr + numQuery, [](const Query &a, const Query &b) { return a.K < b.K; }); for (int t = 0; t < numQuery; ++t) { int K(qr[t].K), pos(qr[t].pos); for (int u = 0; u < numNode; ++u) { if(firstToLoop[idn[u]] >= K) { B[idn[u]].push_back({K, pos}); continue; } int id(firstInLoop[idn[u]]), posn = (posInComp[id] + K - firstToLoop[idn[u]]) % loopOf[id]; result[pos] += (getLeftNode(comp[idc[id]][posn]) == lastNode); } } for (int id = 0; id < 2 * numEdge; ++id) dx[id] = 0; for (int id = 0; id < 2 * numEdge; ++id) { if(!dx[id]) dfsLast(id, -1); } for (int t = 0; t < numQuery; ++t) { //cout << result[t] << '\n'; answer(result[t]); } }

Compilation message (stderr)

garden.cpp:8: warning: ignoring '#pragma GCC optimization' [-Wunknown-pragmas]
    8 | #pragma GCC optimization ("O3")
      | 
garden.cpp:9: warning: ignoring '#pragma GCC optimization' [-Wunknown-pragmas]
    9 | #pragma GCC optimization ("unroll-loops")
      | 
garden.cpp: In function 'void count_routes(int, int, int, int (*)[2], int, int*)':
garden.cpp:100:17: warning: unused variable 'v' [-Wunused-variable]
  100 |             int v(adj[u][it].fi), id(adj[u][it].se);
      |                 ^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...