A. 简单题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int a[25 ];void solve () { int n; cin >> n; for (int i = 1 ; i <= n; i++) { cin >> a[i]; } for (int i = 1 ; i < n; i++) { if ((i & -i) == i) continue ; if (a[i] > a[i + 1 ]) { cout << "No\n" ; return ; } } cout << "Yes\n" ; }
B. 考虑 $x$ 最后单调不增,模拟可以做到 $O(\log^2 + n)$。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 void solve () { int n, q; cin >> n >> q; vi a (n) ; rep (i, n) cin >> a[i]; vi qq; rep (i, q) { int x; cin >> x; if (qq.empty ()) qq.emplace_back (x); else { if (qq.back () <= x) continue ; qq.emplace_back (x); } } ll w[31 ]; memset (w, 0 , sizeof w); for (int j = 0 ; j <= 30 ; j++) { w[j] = 0 ; for (int x : qq) { if (j >= x) { w[j] += 1 << x - 1 ; } } } rep (i, n) { cout << a[i] + w[__lg(a[i] & -a[i])] << " \n" [i + 1 == n]; } }
C. 排序之后贪心。
注意可能 $\lfloor \frac{sum}{2}\rfloor = 0$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 void solve () { int n; cin >> n; ll s = 0 ; vi a (n) ; rep (i, n) { cin >> a[i]; s += a[i]; } s /= 2 ; sort (all (a)); ll ans = 0 ; for (int i = n - 1 ; s; i--) { if (s >= a[i]) { s -= a[i]; a[i] = 0 ; ans += 1 ; } else { a[i] -= s; s = 0 ; ans += 1 ; break ; } } cout << ans + accumulate (all (a), 0LL ) << "\n" ; }
D. 按位,二分。
复杂度 $O(T\log^2)$。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 const int P = 1e9 + 7 ;void solve () { auto solve = [&](ll l, ll r, ll x) { if (l > r) { return 0LL ; } ll c = 0 ; __int128 p = 1 ; while (p * x <= l) { p = p * x; c += 1 ; } ll res = 0 ; for (ll i = l, j; i <= r; i = j + 1 , p = p * x, c++) { ll L = i - 1 , R = r + 1 ; while (R - L > 1 ) { ll M = (L + R) / 2 ; if (p <= M && M < p * x) { L = M; } else { R = M; } } j = L; res += 1ll * (j - i + 1 ) % P * c % P; if (res >= P) { res -= P; } } return res; }; ll l, r; cin >> l >> r; ll ans = 0 ; for (int i = 0 ; i < 62 ; i++) { ll L = 1LL << i; ll R = 1LL << i + 1 ; --R; ans += solve (max (l, L), min (r, R), i); if (ans >= P) { ans -= P; } } cout << ans << "\n" ; }
E. 假做法过题。
考虑 $k$ 越大答案越优秀,这是显然的。
很显然可以 dp,状态为 $dp_{i,j,k}$ 表示这是第 $i$ 个位置,用了 $j$ 次,上一个位置是不是 $0$。
然后可以在平均值附近选 $\sqrt n$ 个,如果数据随机,错误率非常的低。
记得开 ll。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 void solve () { cin >> n >> k; rep (i, n) { cin >> a[i]; } rep (i, 1 , n) { rep (j, 2 ) { rep (nj, 2 ) { int x = a[i - 1 ]; int y = a[i]; if (j == 1 ) { x = 0 ; } if (nj == 1 ) { y = 0 ; } if (gcd (x, y) == 1 ) { coef[i][j][nj] = 1 ; } else { coef[i][j][nj] = 0 ; } } } } rep (c, 0 , 2 ) rep (i, k + 1 ) rep (j, 2 ) dp[c][i][j] = inf, vis[c][i][j] = -1 ; dp[0 ][0 ][0 ] = 0 ; dp[0 ][1 ][1 ] = 0 ; vis[0 ][0 ][0 ] = 0 ; vis[0 ][1 ][1 ] = 0 ; int p = 1 , q = 0 ; for (int i = 1 ; i < n; i++, p ^= 1 , q ^= 1 ) { int l = 1ll * k * (i + 1 ) / n - 500 ; int r = 1ll * k * (i + 1 ) / n + 500 ; cmax (l, 0 ); cmin (r, k); rep (kk, l, r + 1 ) { dp[p][kk][0 ] = dp[p][kk][1 ] = inf; rep (j, 2 ) { rep (nj, 2 ) { if (kk >= nj) { if (vis[q][kk - nj][j] < i - 1 ) continue ; cmin (dp[p][kk][nj], dp[q][kk - nj][j] + coef[i][j][nj]); vis[p][kk][nj] = i; } } } } } cout << min (dp[q][k][0 ], dp[q][k][1 ]) << "\n" ; }
F. 倒着扫描线。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 void solve () { int q; cin >> q; vc<vi> g (1 ) ; vc<vi> qq (q) ; vc<vc<pii>> ad (q); rep (i, q) { int o; cin >> o; if (o == 1 ) { int v; cin >> v; --v; int n = g.size (); g[v].pb (n); g.pb (); qq[i].pb (n); } else { int v, x; cin >> v >> x; --v; ad[i].pb (v, x); } } int n = (int )g.size (); vi dfn (n) ; vi sz (n) ; int c = 0 ; auto dfs = [&](auto &self, int u) -> void { sz[u] = 1 ; dfn[u] = c++; for (auto v : g[u]) { self (self, v); sz[u] += sz[v]; } }; dfs (dfs, 0 ); vc<ll> t (n * 2 ) ; auto add = [&](int x, int v) { if (x == n) { return ; } x += n; while (x) { t[x] += v; x >>= 1 ; } }; auto query = [&](int l, int r) { ll res = 0 ; for (l += n, r += n; l < r; l /= 2 , r /= 2 ) { if (l & 1 ) { res += t[l++]; } if (r & 1 ) { res += t[--r]; } } return res; }; vc<ll> ans (n) ; for (int i = q - 1 ; i >= 0 ; i--) { for (auto [v, x] : ad[i]) { add (dfn[v], x); add (dfn[v] + sz[v], -x); } for (auto v : qq[i]) { ans[v] = query (0 , dfn[v] + 1 ); } } ans[0 ] = query (0 , 1 ); for (int i = 0 ; i < n; i++) { cout << ans[i] << " \n" [i + 1 == n]; } }