voidsolve(){ int n, m; std::cin >> n >> m; std::vector<int> a(n), t; for (int i = 0; i < n; i++) { std::cin >> a[i]; } int ans = 0; for (int i = 1; i < n; i++) { t.push_back(abs(a[i] - a[i - 1])); ans += t.back(); } sort(t.begin(), t.end(), std::greater<int>()); for (int i = 0; i < m - 1; i++) { ans -= t[i]; } std::cout << ans << '\n'; }
signedmain(){ int t = 1; std::cin >> t; while (t--) solve(); return0; }
voidsolve(){ int n; std::cin >> n; std::vector<int> a(n); int t = -1; // -1的二进制为全 1 for (int i = 0; i < n; i++) { std::cin >> a[i]; t &= a[i]; } // 最终结果不为0 直接输出1 if (t) { std::cout << "1\n"; return; } int x = -1, ans = 0; for (int i = 0; i < n; i++) { x &= a[i]; if (x == t) { ans++; x = -1; } } std::cout << ans << '\n'; }
signedmain(){ int t = 1; std::cin >> t; while (t--) solve(); return0; }
D. d
思路:贪心地给每个人先分 t = ⌈g / 2⌉ − 1 个银币,这样使得每个人不会获得的部分是最多的。
设 p 为每个人都发 ⌈g / 2⌉ − 1 个银币最多省下的银币
最后还剩下 k * g - p 个, 因为一开始已经给所有人分了不会获得的上限,因此对于任意一个人,只要多一个银币就会多分一个金 需要分 f = (k * g - p + g - 1) / g 个金
voidsolve(){ int n, k, g; std::cin >> n >> k >> g; int t = (g + 1) / 2 - 1; int p = std::min(n * t, k * g); int f = ((k * g - p) + g - 1) / g; int ans = (k - f) * g; std::cout << ans << '\n'; }
signedmain(){ int t = 1; std::cin >> t; while (t--) solve(); return0; }
voidsolve(){ int n; std::cin >> n; std::vector<int> a(n); for (int i = 0; i < n; i++) { std::cin >> a[i]; } int ans = 0, res = 0; std::set<int> se; // 对左区间进行去重 for (int i = 0; i < n; i++) { res ^= a[i]; ans = std::max(ans, res); // 不需要枚举每一个左区间 for (auto it : se) { ans = std::max(ans, it ^ res); } se.insert(res); } std::cout << ans << '\n'; }
signedmain(){ int t = 1; std::cin >> t; while (t--) solve(); return0; }
voidsolve(){ int n; std::cin >> n; std::vector<int> a(n); for (int i = 0; i < n; i++) { std::cin >> a[i]; } std::vector<int> cnt(1 << 8, 0); int ans = 0; for (auto x : a) { ans = std::max(ans, x); std::vector<int> tem(1 << 8, 0); for (int u = 0; u < 1 << 8; u++) { if (cnt[u]) { tem[u ^ x]++; ans = std::max(ans, u ^ x); } } cnt = tem; cnt[x]++; } std::cout << ans << '\n'; }
signedmain(){ int t = 1; std::cin >> t; while (t--) solve(); return0; }
voidsolve(){ int a, b, c, k; std::cin >> a >> b >> c >> k; int l1 = pow(10, a - 1), r1 = pow(10, a) - 1; int l2 = pow(10, b - 1), r2 = pow(10, b) - 1; int l3 = pow(10, c - 1), r3 = pow(10, c) - 1; for (int i = l1; i <= r1; i++) { int l = std::max(i + l2, l3); int r = std::min(i + r2, r3); if (l > r) { continue; } if (r - l + 1 >= k) { int ans = l + k - 1; std::cout << i << " + " << ans - i << " = " << ans << '\n'; return; } k -= (r - l + 1); } std::cout << "-1\n"; }
signedmain(){ int t = 1; std::cin >> t; while (t--) solve(); return0; }
G. g
思路: 贪心 + 并查集 / set + 树状数组
子串靠前的,位置在子串中靠前的,优先级更大。因此,按子串顺序,子串内从左到右,给 s 的位置规定排名 rk 。
voidadd(int i, int val){ while (i < tree.size()) { tree[i] += val; i += i & -i; } } intget(int i){ int res = 0; while (i > 0) { res += tree[i]; i &= i - 1; } return res; } intquery(int l, int r){ returnget(r) - get(l - 1); } };
voidsolve(){ int n, m, q; std::cin >> n >> m >> q; std::string s; std::cin >> s; s = ' ' + s; int cnt = 0; for (auto ch : s) cnt += (ch == '1');
std::set<int> se; // 维护未被处理的点 for (int i = 1; i <= n + 1; i++) { se.insert(i); }
std::vector<int> rk(n + 1); int idx = 0; BT t(n);
for (int i = 0; i < m; i++) { int l, r; std::cin >> l >> r;
auto it = se.lower_bound(l); while (it != se.end() && *it <= r) { int j = *it; rk[j] = ++idx; if (s[j] == '1') { t.add(rk[j], 1); } it = se.erase(it); // 标记为已处理 } }
while (q--) { int x; std::cin >> x; if (s[x] == '0') { s[x] = '1'; cnt++; if (rk[x]) t.add(rk[x], 1); } else { s[x] = '0'; cnt--; if (rk[x]) t.add(rk[x], -1); } int ans = std::min(cnt, idx); std::cout << ans - t.get(ans) << '\n'; } }
signedmain(){ int t = 1; // std::cin >> t; while (t--) solve(); return0; }