放个代码,F提供一个不动态开点的方法
A题:
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::string s;
std::cin >> s;
int ans = 0;
for (int i = 1; i < s.size(); i ++ ) {
if (s[i] != s[i - 1]) {
ans ++;
}
}
std::cout << ans << '\n';
return 0;
}
B题:
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::string s;
std::cin >> s;
int len = 0;
i64 ans = 0;
for (int i = 1; i < s.size(); i ++ ) {
if (s[i] != s[i - 1]) {
if (len == 0) {
len = 2;
}else {
len ++;
}
}else {
if (len) {
ans += (i64)(len - 1) * len / 2;
}
len = 0;
}
}
if (len) {
ans += (i64)(len - 1) * len / 2;
}
std::cout << ans << '\n';
return 0;
}
C题:
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int a, b, k;
std::cin >> a >> b >> k;
if (k == 0) {
if (a && b) {
std::cout << -1 << '\n';
}else {
if (a) {
std::cout << std::string(a, '0') << '\n';
}else {
std::cout << std::string(b, '1') << '\n';
}
}
return;
}
if (k >= 2 * std::min(a, b) + (a != b)) {
std::cout << -1 << '\n';
return;
}
//101010111111111
std::vector<int> cnt(2 * std::min(a, b) + 3, 1);
cnt[2 * std::min(a, b) + 1] = std::max(a, b) - std::min(a, b);
cnt[2 * std::min(a, b) + 2] = 0;
int ed = 2 * std::min(a, b) + 1;
while (ed - 1 > k) {
cnt[ed - 2] += cnt[ed];
cnt[ed] = 0;
ed --;
}
for (int i = 1; cnt[i]; i ++ ) {
if (i & 1) {
if (a >= b) {
std::cout << std::string(cnt[i], '0');
}else {
std::cout << std::string(cnt[i], '1');
}
}else {
if (a >= b) {
std::cout << std::string(cnt[i], '1');
}else {
std::cout << std::string(cnt[i], '0');
}
}
}
std::cout << '\n';
return;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int tt = 1; std::cin >> tt;
while (tt -- ) solve();
return 0;
}
D题:
#include <bits/stdc++.h>
using i64 = long long;
constexpr i64 inf = 1E15;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, x, y;
std::cin >> n >> x >> y;
std::string s;
std::cin >> s;
std::vector<i64> dp(n, inf);
std::vector<int> next1(n), next0(n);
int one = n, zero = n;
for (int i = n - 1; i >= 0; i -- ) {
next1[i] = one, next0[i] = zero;
if (s[i] == '1') {
one = i;
}else {
zero = i;
}
}
dp[0] = 0;
for (int i = 0; i < n; i ++ ) {
if (next1[i] < n) {
if (s[i] == '1') {
dp[next1[i]] = std::min(dp[next1[i]], dp[i] + x);
}else {
dp[next1[i]] = std::min(dp[next1[i]], dp[i] + y);
}
}
if (next0[i] < n) {
if (s[i] == '0') {
dp[next0[i]] = std::min(dp[next0[i]], dp[i] + x);
}else {
dp[next0[i]] = std::min(dp[next0[i]], dp[i] + y);
}
}
}
std::cout << dp[n - 1] << '\n';
return 0;
}
E题:
#include <bits/stdc++.h>
using i64 = long long;
template<class T>
constexpr T power(T a, i64 b) {
T res = 1;
for (; b; b /= 2, a *= a) {
if (b % 2) {
res *= a;
}
}
return res;
}
constexpr i64 mul(i64 a, i64 b, i64 p) {
i64 res = a * b - i64(1.L * a * b / p) * p;
res %= p;
if (res < 0) {
res += p;
}
return res;
}
template<int P>
struct MInt {
int x;
constexpr MInt() : x{} {}
constexpr MInt(i64 x) : x{norm(x % getMod())} {}
static int Mod;
constexpr static int getMod() {
if (P > 0) {
return P;
} else {
return Mod;
}
}
constexpr static void setMod(int Mod_) {
Mod = Mod_;
}
constexpr int norm(int x) const {
if (x < 0) {
x += getMod();
}
if (x >= getMod()) {
x -= getMod();
}
return x;
}
constexpr int val() const {
return x;
}
explicit constexpr operator int() const {
return x;
}
constexpr MInt operator-() const {
MInt res;
res.x = norm(getMod() - x);
return res;
}
constexpr MInt inv() const {
assert(x != 0);
return power(*this, getMod() - 2);
}
constexpr MInt &operator*=(MInt rhs) & {
x = 1LL * x * rhs.x % getMod();
return *this;
}
constexpr MInt &operator+=(MInt rhs) & {
x = norm(x + rhs.x);
return *this;
}
constexpr MInt &operator-=(MInt rhs) & {
x = norm(x - rhs.x);
return *this;
}
constexpr MInt &operator/=(MInt rhs) & {
return *this *= rhs.inv();
}
friend constexpr MInt operator*(MInt lhs, MInt rhs) {
MInt res = lhs;
res *= rhs;
return res;
}
friend constexpr MInt operator+(MInt lhs, MInt rhs) {
MInt res = lhs;
res += rhs;
return res;
}
friend constexpr MInt operator-(MInt lhs, MInt rhs) {
MInt res = lhs;
res -= rhs;
return res;
}
friend constexpr MInt operator/(MInt lhs, MInt rhs) {
MInt res = lhs;
res /= rhs;
return res;
}
friend constexpr std::istream &operator>>(std::istream &is, MInt &a) {
i64 v;
is >> v;
a = MInt(v);
return is;
}
friend constexpr std::ostream &operator<<(std::ostream &os, const MInt &a) {
return os << a.val();
}
friend constexpr bool operator==(MInt lhs, MInt rhs) {
return lhs.val() == rhs.val();
}
friend constexpr bool operator!=(MInt lhs, MInt rhs) {
return lhs.val() != rhs.val();
}
};
constexpr int P = 1000000007;
using Z = MInt<P>;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::string s;
std::cin >> s;
int n = s.size();
std::vector<std::vector<Z>> dp(2, std::vector<Z>(13));
if (s[0] != '?') {
dp[s[0] - '0'][s[0] - '0'] = 1;
}else {
dp[1][1] = dp[0][0] = 1;
}
for (int i = 1; i < n; i ++ ) {
std::vector<std::vector<Z>> ndp(2, std::vector<Z>(13));
for (int j = 0; j < 2; j ++ ) {
for (int k = 0; k < 13; k ++ ) {
ndp[j][k * 10 % 13] += dp[j][k];
dp[j][k] = 0;
}
}
if (s[i] == '0') {
for (int j = 0; j < 13; j ++ ) {
dp[0][j] += ndp[0][j] + ndp[1][j];
}
}else if (s[i] == '1') {
for (int j = 0; j < 13; j ++ ) {
dp[1][(j + 1) % 13] += ndp[1][j] + ndp[0][j];
}
}else {
for (int j = 0; j < 13; j ++ ) {
dp[0][j] += ndp[0][j] + ndp[1][j];
}
for (int j = 0; j < 13; j ++ ) {
dp[1][(j + 1) % 13] += ndp[1][j] + ndp[0][j];
}
}
}
if (s.back() != '?') {
std::cout << dp[s.back() - '0'][0] << '\n';
}else {
std::cout << (dp[0][0] + dp[1][0]) << '\n';
}
return 0;
}
F题:
做法:离线线段树 首先我们将所有要用到的点进行离散化,这样就可以缩水到4e5个来进行线段树
然后对于1,3,5,9,1000,以下述方式放入线段树
我们放入[1,1],(1,3),[3,3],(3,5),[5,5],(5,9),[9,9],(9,1000),[1000,1000]
然后分成最后变成01010或者1010进行分析,其实是一样的,我们只需统计一个same即可,same是和0101上数字相同的个数,之后就是纯懒标记线段树了
#include <bits/stdc++.h>
using i64 = long long;
constexpr int inf = 1E9 + 7;
template<class Info, class Tag>
struct LazySegmentTree {
int n;
std::vector<Info> info;
std::vector<Tag> tag;
LazySegmentTree() : n(0) {}
LazySegmentTree(int n_, Info v_ = Info()) {
init(n_, v_);
}
template<class T>
LazySegmentTree(std::vector<T> init_) {
init(init_);
}
void init(int n_, Info v_ = Info()) {
init(std::vector(n_, v_));
}
template<class T>
void init(std::vector<T> init_) {
n = init_.size();
info.assign(4 << (int)std::log2(n), Info());
tag.assign(4 << (int)std::log2(n), Tag());
std::function<void(int, int, int)> build = [&](int p, int l, int r) {
if (r - l == 1) {
info[p] = init_[l];
return;
}
int m = (l + r) / 2;
build(2 * p, l, m);
build(2 * p + 1, m, r);
pull(p);
};
build(1, 0, n);
}
void pull(int p) {
info[p] = info[2 * p] + info[2 * p + 1];
}
void apply(int p, const Tag &v) {
info[p].apply(v);
tag[p].apply(v);
}
void push(int p) {
apply(2 * p, tag[p]);
apply(2 * p + 1, tag[p]);
tag[p] = Tag();
}
void modify(int p, int l, int r, int x, const Info &v) {
if (r - l == 1) {
info[p] = v;
return;
}
int m = (l + r) / 2;
push(p);
if (x < m) {
modify(2 * p, l, m, x, v);
} else {
modify(2 * p + 1, m, r, x, v);
}
pull(p);
}
void modify(int p, const Info &v) {
modify(1, 0, n, p, v);
}
Info rangeQuery(int p, int l, int r, int x, int y) {
if (l >= y || r <= x) {
return Info();
}
if (l >= x && r <= y) {
return info[p];
}
int m = (l + r) / 2;
push(p);
return rangeQuery(2 * p, l, m, x, y) + rangeQuery(2 * p + 1, m, r, x, y);
}
Info rangeQuery(int l, int r) {
return rangeQuery(1, 0, n, l, r);
}
void rangeApply(int p, int l, int r, int x, int y, const Tag &v) {
if (l >= y || r <= x) {
return;
}
if (l >= x && r <= y) {
apply(p, v);
return;
}
int m = (l + r) / 2;
push(p);
rangeApply(2 * p, l, m, x, y, v);
rangeApply(2 * p + 1, m, r, x, y, v);
pull(p);
}
void rangeApply(int l, int r, const Tag &v) {
return rangeApply(1, 0, n, l, r, v);
}
void half(int p, int l, int r) {
if (info[p].act == 0) {
return;
}
if ((info[p].min + 1) / 2 == (info[p].max + 1) / 2) {
apply(p, {-(info[p].min + 1) / 2});
return;
}
int m = (l + r) / 2;
push(p);
half(2 * p, l, m);
half(2 * p + 1, m, r);
pull(p);
}
void half() {
half(1, 0, n);
}
template<class F>
int findFirst(int p, int l, int r, int x, int y, F &&pred) {
if (l >= y || r <= x) {
return -1;
}
if (l >= x && r <= y && !pred(info[p])) {
return -1;
}
if (r - l == 1) {
return l;
}
int m = (l + r) / 2;
push(p);
int res = findFirst(2 * p, l, m, x, y, pred);
if (res == -1) {
res = findFirst(2 * p + 1, m, r, x, y, pred);
}
return res;
}
template<class F>
int findFirst(int l, int r, F &&pred) {
return findFirst(1, 0, n, l, r, pred);
}
template<class F>
int findLast(int p, int l, int r, int x, int y, F &&pred) {
if (l >= y || r <= x) {
return -1;
}
if (l >= x && r <= y && !pred(info[p])) {
return -1;
}
if (r - l == 1) {
return l;
}
int m = (l + r) / 2;
push(p);
int res = findLast(2 * p + 1, m, r, x, y, pred);
if (res == -1) {
res = findLast(2 * p, l, m, x, y, pred);
}
return res;
}
template<class F>
int findLast(int l, int r, F &&pred) {
return findLast(1, 0, n, l, r, pred);
}
void maintainL(int p, int l, int r, int pre) {
if (info[p].difl > 0 && info[p].maxlowl < pre) {
return;
}
if (r - l == 1) {
info[p].max = info[p].maxlowl;
info[p].maxl = info[p].maxr = l;
info[p].maxlowl = info[p].maxlowr = -inf;
return;
}
int m = (l + r) / 2;
push(p);
maintainL(2 * p, l, m, pre);
pre = std::max(pre, info[2 * p].max);
maintainL(2 * p + 1, m, r, pre);
pull(p);
}
void maintainL() {
maintainL(1, 0, n, -1);
}
void maintainR(int p, int l, int r, int suf) {
if (info[p].difr > 0 && info[p].maxlowr < suf) {
return;
}
if (r - l == 1) {
info[p].max = info[p].maxlowl;
info[p].maxl = info[p].maxr = l;
info[p].maxlowl = info[p].maxlowr = -inf;
return;
}
int m = (l + r) / 2;
push(p);
maintainR(2 * p + 1, m, r, suf);
suf = std::max(suf, info[2 * p + 1].max);
maintainR(2 * p, l, m, suf);
pull(p);
}
void maintainR() {
maintainR(1, 0, n, -1);
}
};
struct Tag {
int t1 = 0, t2 = 0;
Tag() {};
Tag(int a, int b) : t1(a), t2(b) {};
void apply(const Tag &t) & {
if (t.t2) {
t1 = t.t1;
t2 = t.t2;
}else {
t1 += t.t1;
}
}
};
struct Info {
int st = 0;
int len = 0;
int same = 0;
Info() {};
Info(int a, int b, int c) : st(a), len(b), same(c) {};
void apply(const Tag &t) & {
if (t.t2) {
if (st & 1) {
same = len / 2;
}else {
same = (len + 1) / 2;
}
if (t.t1 & 1) {
same = len - same;
}
}else if (t.t1 & 1) {
same = len - same;
}
}
};
Info operator+(const Info &a, const Info &b) {
Info c;
c.st = std::min(a.st, b.st);
c.len = a.len + b.len;
c.same = a.same + b.same;
return c;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, q;
std::cin >> n >> q;
std::vector<std::array<int, 5>> query(q);
std::vector<int> s;
for (int i = 0; i < q; i ++ ) {
int op, l, r;
std::cin >> op >> l >> r;
query[i] = {op, l, r, l, r};
s.push_back(l);
s.push_back(r);
}
std::sort(s.begin(), s.end());
s.erase(std::unique(s.begin(), s.end()), s.end());
for (int i = 0; i < q; i ++ ) {
query[i][3] = std::lower_bound(s.begin(), s.end(), query[i][3]) - s.begin();
query[i][4] = std::lower_bound(s.begin(), s.end(), query[i][4]) - s.begin();
}
std::vector<Info> to;
std::map<int, int> lsh;
for (int i = 0, j = 0; i < s.size(); i ++ ) {
if (i) {
if (s[i] - s[i - 1] > 1) {
int len = s[i] - 1 - s[i - 1], same = 0;
if ((s[i - 1] + 1) % 2 == 1) {
same = (len + 1) / 2;
}else {
same = len / 2;
}
to.push_back({s[i - 1] + 1, len, same});
j ++;
}
}
to.push_back({s[i], 1, (s[i] & 1)});
lsh[s[i]] = j ++;
}
for (int i = 0; i < q; i ++ ) {
query[i][1] = lsh[query[i][1]];
query[i][2] = lsh[query[i][2]];
}
LazySegmentTree<Info, Tag> seg(to);
for (auto [op, l, r, l1, r1] : query) {
if (op == 1) {
seg.rangeApply(l, r + 1, {0, 1});
}else if (op == 2) {
seg.rangeApply(l, r + 1, {1, 0});
}else {
int t = seg.rangeQuery(l, r + 1).same;
std::cout << s[r1] - s[l1] + 1 - std::max(t, s[r1] - s[l1] + 1 - t) << '\n';
}
}
return 0;
}