Submission #299267

#TimeUsernameProblemLanguageResultExecution timeMemory
299267ToMmyDongTropical Garden (IOI11_garden)C++17
69 / 100
5031 ms76272 KiB
#include <bits/extc++.h> using namespace std; using namespace __gnu_pbds; typedef long long ll; typedef pair<int,int> pii; #define ALL(i) i.begin(),i.end() #define SZ(i) int(i.size()) #define X first #define Y second #define eb emplace_back #define pb push_back #ifdef tmd #define debug(...) fprintf(stderr,"#%d-(%s)=",__LINE__,#__VA_ARGS__);_do(__VA_ARGS__); template<typename T> void _do(T &&x) {cerr<<x<<endl;} template<typename T, typename ...S> void _do(T &&x, S &&...y) {cerr<<x<<",";_do(y...);} template<typename IT> ostream& printRng (ostream& os, IT bg, IT ed) { os << "{"; for (IT it=bg; it!=ed; it++) { if (it == bg) os << *it; else os << "," << *it; } return os << "}"; } template<typename T> ostream& operator << (ostream& os, const vector<T>& v) {return printRng(os,ALL(v));} template<typename T, typename S> ostream& operator << (ostream& os, const pair<T,S>& v) {return os<<"("<<v.X<<","<<v.Y<<")";} #else #define debug(...) #endif #include "garden.h" #include "gardenlib.h" const int INF = 0x3f3f3f3f; int n, m, p; struct Edge { int to, w, id; bool operator < (const Edge &e) const { return w < e.w; } }; vector<int> ed; vector<vector<Edge>> edge; vector<int> to, csz, dis, dfn, cdis, croot, cid, cpos; vector<vector<int>> cycle; const int MAXN = 150002*2; const int MAXLG = 32; int anc[MAXLG][MAXN]; int tme = 0; int init; void make_csz (int nd) { dfn[nd] = tme++; csz[nd] = INF; if (csz[to[nd]] == -1) make_csz(to[nd]); else if (csz[to[nd]] == INF) { if (dfn[to[nd]] >= init) { csz[to[nd]] = tme - dfn[to[nd]]; int y = to[nd]; vector<int> nc; for (int j=0; j<csz[to[nd]]; j++) { cpos[y] = SZ(nc); nc.eb(y); cdis[y] = 0; cid[y] = SZ(cycle); y = to[y]; } cycle.eb(nc); } } csz[nd] = csz[to[nd]]; if (cdis[nd] != 0) cdis[nd] = cdis[to[nd]] + 1; } void make_dis (int nd) { dis[nd] = INF; if (dis[to[nd]] == -1) make_dis(to[nd]); dis[nd] = dis[to[nd]] + 1; } void build () { assert(m*2 == SZ(to)); for (int i=0; i<m*2; i++) { anc[0][i] = to[i]; } for (int j=1; j<MAXLG; j++) { for (int i=0; i<m*2; i++) { anc[j][i] = anc[j-1][anc[j-1][i]]; } } } vector<int> g, res, go; vector<vector<int> > rev; vector<int> chain; void make_tree (int nd, int par, int rt) { chain.eb(nd); debug(nd, chain); int sz = SZ(chain); croot[nd] = rt; if (go[nd]) { for (int i=0; i<SZ(g); i++) { if (sz-1-g[i] >= 0) { res[i] += ed[chain[sz-1-g[i]]] == p; if (ed[chain[sz-1-g[i]]] == p) { debug(i); } } } } for (int v : rev[nd]) { if (v != par && cdis[v] != 0) { make_tree(v, nd, rt); } } chain.pop_back(); } void count_routes(int N, int M, int P, int R[][2], int Q, int G[]) { edge.resize(N); n = N; m = M; p = P; srand(time(0)); #ifdef tmdd p = rand() % n; debug(p); for (int i=0; i<Q; i++) { G[i] = rand() % 30 + 1; debug(G[i]); } debug(P); #endif for (int i=0; i<Q; i++) { g.eb(G[i]-1); } int cnt = 0; for (int i=0; i<M; i++) { int u = R[i][0], v = R[i][1]; edge[u].pb({v, i, cnt++}); edge[v].pb({u, i, cnt++}); } ed.resize(cnt); rev.resize(cnt); for (int i=0; i<n; i++) { for (auto e : edge[i]) { ed[e.id] = e.to; } } to.resize(cnt), csz.resize(cnt, -1), dis.resize(cnt, -1); dfn.resize(cnt, 0); cdis.resize(cnt, -1); croot.resize(cnt), cid.resize(cnt), cpos.resize(cnt); for (int i=0; i<n; i++) { sort(ALL(edge[i])); } vector<int> start; go.resize(cnt); for (int i=0; i<n; i++) { for (const Edge &e : edge[i]) { int x = e.to; if (x == p) dis[e.id] = 0; if (SZ(edge[x]) == 1) { to[e.id] = edge[x][0].id; } else { to[e.id] = edge[x][edge[x][0].w == e.w ? 1 : 0].id; } rev[to[e.id]].eb(e.id); } start.eb(edge[i][0].id); go[edge[i][0].id] = true; } build(); debug(to); debug(start); debug(ed); for (int i=0; i<cnt; i++) { if (csz[i] == -1) { init = tme; make_csz(i); } } debug(cdis, csz); for (int i=0; i<cnt; i++) { if (dis[i] == -1) { make_dis(i); } } res.resize(Q); debug(cycle, cdis); for (auto &v : cycle) { for (int r : v) { make_tree(r, -1, r); } } debug(croot, cid, cpos); for (int i=0; i<n; i++) { vector<pii> qry; if (dis[edge[i][0].id] >= INF) continue; for (int j=0; j<Q; j++) { int id = edge[i][0].id; int d = G[j] - 1; if (d > cdis[id]) { d = (d-cdis[id]) % csz[id]; int rt = croot[id]; int cp = cpos[rt]; assert(csz[id] == csz[rt]); int tg = cycle[cid[rt]][(cp + d) % csz[id]]; res[j] += ed[tg] == p; if (ed[tg] == p) { debug(id, j, rt, d, tg, cp); } } qry.eb(d, j); } } for (int _=0; _<Q; _++) { answer(res[_]); /* int ans = 0; for (int x : start) { if (dis[x] < G[_]) { ans += (G[_] - 1 - dis[x]) % csz[x] == 0; } } */ #ifdef tmd int ans = 0; for (int x : start) { for (int i=0; i<G[_]-1; i++) { x = to[x]; } if (ed[x] == p) ans++; } if (ans != res[_]) { debug(G[_], ans, res[_]); } assert(ans == res[_]); #endif /* for (int i=0; i<N; i++) { int x = i; int prv = -1; for (int j=0; j<G[_]; j++) { debug(x); if (edge[x][0].w != prv || SZ(edge[x]) == 1) { prv = edge[x][0].w; x = edge[x][0].to; } else { prv = edge[x][1].w; x = edge[x][1].to; } } debug(i, x); ans += x == p; } */ } } /* 6 5 2 1 3 0 1 1 2 3 4 3 5 5 32 4 2 1 23 0 0 0 0 0 */
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...