Submission #1042492

#TimeUsernameProblemLanguageResultExecution timeMemory
1042492sleepntsheepInside information (BOI21_servers)C11
80 / 100
3551 ms32340 KiB
#include <string.h> #include <stdio.h> #include <stdlib.h> int max(int i, int j) { return i > j ? i : j; } /* * For "Q" queries, use LCA + prefix sum on tree ~ 3O(lgn) [for finding lca and almost-lca] * * Every B queries of any type, do naive dp on tree (reverse edge order) * to find answer for "C" queries ~ O(n) * * On "C" queries, use cached answer from above and count all edges that appeared after that (by "Q") * ~ O(B lgn) * * * Time complexity = O(N^2 / B) + O(N lgn) + O(N B lgn) * * Let B = sqrt(N / lgN) * * Should be able to optimize to O(N^1.5) using https://codeforces.com/blog/entry/71567?mobile=true&locale=en */ #define N 120001 #define B 900 int n, q, pp[N], dd[N], up[N], temp, inc[N], tin[N], tout[N], timer, hld[N], ds[N], sz[N]; int ds_find(int i) { return ds[i] == i ? i : (ds[i] = ds_find(ds[i])); } void pus_(int **eh, int *eo, int i, int j) { int o = eo[i]++; if (0 == o) eh[i] = (int*)malloc(2 * sizeof **eh); else if (0 == (o & o - 1)) eh[i] = (int*)realloc(eh[i], 2 * o * sizeof **eh); eh[i][o] = j; } int *eh[N], *fh[N], eo[N]; void link(int u, int v, int w) { pus_(eh, eo, u, v); --eo[u]; pus_(fh, eo, u, w); pus_(eh, eo, v, u); --eo[v]; pus_(fh, eo, v, w); } void dfs(int u, int p) { sz[u] = 1; inc[u] = (up[u] > up[p]) + inc[p]; for (int j = 0; j < eo[u]; ++j) if (eh[u][j] != p) { int v = eh[u][j]; dd[v] = dd[u] + 1; pp[v] = u; up[v] = fh[u][j]; dfs(v, u); sz[u] += sz[v]; } for (int j = 0; j < eo[u]; ++j) if (eh[u][j] == p) { int ww = fh[u][j]; for (int k = j + 1; k < eo[u]; ++k) eh[u][k - 1] = eh[u][k], fh[u][k - 1] = fh[u][k]; --eo[u]; eh[u][eo[u]] = p; fh[u][eo[u]] = ww; break; } for (int j = 0; j < eo[u]; ++j) { int v = eh[u][j]; if (sz[v] > sz[eh[u][0]]) { temp = eh[u][0], eh[u][0] = v, eh[u][j] = temp; temp = fh[u][0], fh[u][0] = fh[u][j], fh[u][j] = temp; } } } void efs(int u, int hd) { tin[u] = timer++; hld[u] = hd; if (eo[u]) efs(eh[u][0], hd); for (int j = 1; j < eo[u]; ++j) efs(eh[u][j], eh[u][j]); tout[u] = timer - 1; } int lca(int u, int v) { while (hld[u] != hld[v]) { if (dd[hld[u]] >= dd[hld[v]]) u = pp[hld[u]]; else v = pp[hld[v]]; } return dd[u] <= dd[v] ? u : v; } struct Query { char type[2]; int a, b; } qq[N * 2]; int navigate(int u, int v) { int lb = -1, ub = eo[u]; while (ub-lb>1){ int md=lb+(ub-lb)/2; if(tin[eh[u][md]]<=tin[v])lb=md; else ub=md; } return eh[u][lb]; } /* u = data node, v = ask node */ int query_yesno(int u, int v, int time) { if (u == v) return 1; int a = lca(u, v); int va, ua; if (u == a) { va = navigate(a, v); return inc[v] - inc[va] == dd[v] - dd[va] && up[v] <= time; } if (v == a) { ua = navigate(a, u); return inc[u] - inc[ua] == 0 && up[ua] <= time; } va = navigate(a, v); ua = navigate(a, u); return (dd[v] - dd[va] == inc[v] - inc[va]) && (inc[u] - inc[ua] == 0) && up[va] > up[ua] && up[v] <= time; } int dp[N]; void build(int ii, int tme) { for (int i = 1; i <= n; ++i) dp[i] = 1; for (int i = 1; i <= n; ++i) ds_find(i); for (int i = ii; i >= 0; --i) { if (qq[i].type[0] != 'S') continue; int x = dp[qq[i].a], y = dp[qq[i].b]; dp[qq[i].a] += y; dp[qq[i].b] += x; } } int counted[N]; int main() { scanf("%d%d", &n, &q); for (int i = 1; i <= n; ++i) ds[i] = i; q = n + q - 1; for (int j = 0, i = 0; i < q; ++i) { int a, b = 0; char *s = qq[i].type; scanf(" %s%d", s, &a); if (s[0] == 'S') { scanf("%d", &b); link(a, b, j++); } else if (s[0] == 'Q') scanf("%d", &b); qq[i].a = a, qq[i].b = b; } up[1] = 1e9; pp[1] = 1; dfs(1, 1); efs(1, 1); build(-1, -1); int at = 0; for (int j = 0, i = 0; i < q; ++i) { if (qq[i].type[0] == 'S') ++j; if (i % B == 0) { for (int k = at; k <= i; ++k) if (qq[k].type[0] == 'S') ds[ds_find(qq[k].a)] = qq[k].b; build(i, j - 1); at = i + 1; } if (qq[i].type[0] == 'Q') puts(query_yesno(qq[i].b, qq[i].a, j - 1) ? "yes": "no"); else if (qq[i].type[0] == 'C') { int focus = qq[i].a; int addition = 0; for (int k = at; k < i; ++k) if (qq[k].type[0] == 'S') { int a = qq[k].a, b = qq[k].b; if (counted[a] != i + 1 && ds[a] != ds[focus] && query_yesno(focus, a, j - 1)) ++addition, counted[a] = i + 1; if (counted[b] != i + 1 && ds[b] != ds[focus] && query_yesno(focus, b, j - 1)) ++addition, counted[b] = i + 1; } printf("%d\n", dp[focus] + addition); } } }

Compilation message (stderr)

servers.c: In function 'pus_':
servers.c:36:26: warning: suggest parentheses around '-' in operand of '&' [-Wparentheses]
   36 |     else if (0 == (o & o - 1)) eh[i] = (int*)realloc(eh[i], 2 * o * sizeof **eh);
      |                        ~~^~~
servers.c: In function 'main':
servers.c:157:5: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  157 |     scanf("%d%d", &n, &q);
      |     ^~~~~~~~~~~~~~~~~~~~~
servers.c:166:9: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  166 |         scanf(" %s%d", s, &a);
      |         ^~~~~~~~~~~~~~~~~~~~~
servers.c:168:13: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  168 |             scanf("%d", &b);
      |             ^~~~~~~~~~~~~~~
servers.c:171:13: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  171 |             scanf("%d", &b);
      |             ^~~~~~~~~~~~~~~
#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...
#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...