Submission #726905

#TimeUsernameProblemLanguageResultExecution timeMemory
726905MadokaMagicaFanPrize (CEOI22_prize)C++14
100 / 100
2093 ms312908 KiB
#include "bits/stdc++.h" using namespace std; using ll = long long; using vi = vector<int>; using pi = pair<int, int>; const ll inf = 1e9; #define sz(v) ((int)v.size()) #define pb push_back #define endl '\n' #define fst first #define scn second #define ONPC vi sp; void ask(int a, int b) { printf("? %d %d\n", a, b); } struct tree{ vi p; vi d; vi et; vi in; vi f; int root; int n; vector<vi> adj; vector<vector<array<int,2>>> sdj; vector<ll> paiu; vector<bool> vis; tree(int _n) { n = _n; p.assign(n,0); d.assign(n,0); paiu.assign(n,0); d[0] = n+5; in.assign(n,0); adj.assign(n,{}); sdj.assign(n,{}); vis.assign(n,0); } void build() { for (int i = 1; i < n; ++i) if (p[i] == -1) root = i; for (int i = 1; i < n; ++i) { if (p[i] == -1) continue; /* adj[i].pb(p[i]); */ adj[p[i]].pb(i); } dfs1(root); f.assign(4*sz(et), 0); build_aint(1,0,sz(et)-1); return; } void dfs1(int x) { in[x] = sz(et); et.pb(x); for (int u : adj[x]) { d[u] = d[x]+1; dfs1(u); et.pb(x); } return; } int merge_aint(int a, int b) { if (d[a] > d[b]) return b; return a; } int build_aint(int i, int l, int r) { int mid = (l+r)>>1; if (l == r) { f[i] = et[l]; return f[i]; } f[i] = merge_aint( build_aint(i<<1, l, mid), build_aint(i<<1|1, mid+1, r)); return f[i]; } int query_aint(int i, int l, int r, int tl, int tr) { int mid = (l+r)>>1; if (tr < l || r < tl) return 0; if (tl <= l && r <= tr) return f[i]; int a1 = query_aint(i<<1, l, mid, tl, tr); int a2 = query_aint(i<<1|1, mid+1, r, tl, tr); return merge_aint(a1,a2); return merge_aint( query_aint(i<<1, l, mid, tl, tr), query_aint(i<<1|1, mid+1, r, tl, tr)); } int lca(int a, int b) { if (in[a] > in[b]) swap(a,b); return query_aint(1, 0, sz(et)-1,in[a], in[b]); } int getnodes(int x, int k) { if (!k) return 0; /* Useless */ --k; sp.pb(x); for (int u : adj[x]) { if (!k) return 0; k = getnodes(u,k); } return k; } void dfs2(int x, ll v) { if (vis[x]) return; vis[x] = 1; paiu[x]=v; for (auto u : sdj[x]) dfs2(u[0], u[1]+v); } ll dist(int a, int b) { return paiu[a] + paiu[b] - 2ll*paiu[lca(a,b)]; } }; #ifdef ONPC void solve() { int n, k, q, t; scanf("%d %d %d %d", &n, &k, &q, &t); tree t1(n+1), t2(n+1); for (int i = 0; i < n; ++i) scanf("%d", &t1.p[i+1]); for (int i = 0; i < n; ++i) scanf("%d", &t2.p[i+1]); t1.build(); t2.build(); t1.getnodes(t1.root, k); printf("%d", sp[0]); for (int i = 1; i < k; ++i) printf(" %d", sp[i]); printf("\n"); vector<array<int, 2>> qq; for (int i = 0; i < k; ++i) { qq.pb({t2.in[sp[i]], sp[i]}); } sort(qq.begin(), qq.end()); for (int i = 0; i < k-1; ++i) ask(qq[i][1], qq[i+1][1]); printf("!\n"); fflush(stdout); int d1, d2, lc; int a, b; for (int i = 0; i < k-1; ++i) { scanf("%d %d %d %d", &d1, &d2, &a, &b); lc = t1.lca(qq[i][1], qq[i+1][1]); if (lc != qq[i][1]) t1.sdj[lc].pb({qq[i][1], d1}); if (lc != qq[i][1]) t1.sdj[qq[i][1]].pb({lc,-d1}); if (lc != qq[i+1][1]) t1.sdj[lc].pb({qq[i+1][1], d2}); if (lc != qq[i+1][1]) t1.sdj[qq[i+1][1]].pb({lc,-d2}); d1 = a; d2 = b; lc = t2.lca(qq[i][1], qq[i+1][1]); if (lc != qq[i][1]) t2.sdj[lc].pb({qq[i][1], d1}); if (lc != qq[i][1]) t2.sdj[qq[i][1]].pb({lc,-d1}); if (lc != qq[i+1][1]) t2.sdj[lc].pb({qq[i+1][1], d2}); if (lc != qq[i+1][1]) t2.sdj[qq[i+1][1]].pb({lc,-d2}); } t1.dfs2(qq[0][1], 0); t2.dfs2(qq[0][1], 0); vector<array<ll,2>> ans; for (int i = 0; i < t; ++i) { scanf("%d %d", &d1, &d2); ans.pb({t1.dist(d1, d2), t2.dist(d1,d2)}); } for (int i = 0; i < t; ++i) { printf("%lld %lld\n", ans[i][0], ans[i][1]); } fflush(stdout); } int32_t main(int argc, char **argv) { if (argc>1) freopen(argv[1], "r", stdin); solve(); } #endif

Compilation message (stderr)

Main.cpp: In function 'void solve()':
Main.cpp:164:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  164 |     scanf("%d %d %d %d", &n, &k, &q, &t);
      |     ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Main.cpp:166:38: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  166 |     for (int i = 0; i < n; ++i) scanf("%d", &t1.p[i+1]);
      |                                 ~~~~~^~~~~~~~~~~~~~~~~~
Main.cpp:167:38: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  167 |     for (int i = 0; i < n; ++i) scanf("%d", &t2.p[i+1]);
      |                                 ~~~~~^~~~~~~~~~~~~~~~~~
Main.cpp:195:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  195 |         scanf("%d %d %d %d", &d1, &d2, &a, &b);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Main.cpp:216:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  216 |         scanf("%d %d", &d1, &d2);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~
Main.cpp: In function 'int32_t main(int, char**)':
Main.cpp:230:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  230 |         freopen(argv[1], "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~
#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...