A
懒标记线段树,区间修改,区间查询。
。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
template<class Info, class Tag>
struct LazySegmentTree {
int n;
vector<Info> info;
vector<Tag> tag;
LazySegmentTree() : n(0) {}
LazySegmentTree(int n_, Info v_ = Info()) {
init(n_, v_);
}
template<class T>
LazySegmentTree(vector<T> init_) {
init(init_);
}
void init(int n_, Info v_ = Info()) {
init(vector(n_, v_));
}
template<class T>
void init(vector<T> init_) {
n = init_.size();
info.assign(4 << __lg(n), Info());
tag.assign(4 << __lg(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);
}
template<class F>
int findFirst(int p, int l, int r, int x, int y, F pred) {
if (l >= y || r <= x || !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 || !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);
}
};
struct Tag {
int x;
Tag(int x = 0) : x(x) {};
void apply(const Tag &t) {
x ^= t.x;
}
};
struct Info {
int c0, c1, c;
Info(int c0 = 0, int c1 = 0, int c = -1) : c0(c0), c1(c1), c(c) {
}
void apply(const Tag &t) {
if (t.x) {
swap(c0, c1);
c ^= 1;
}
}
};
Info operator+(const Info &a, const Info &b) {
return Info(a.c0 + b.c0, a.c1 + b.c1);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
string s;
cin >> n >> m >> s;
vector<Info> a(n);
for (int i = 0; i < n; i++) {
a[i].c = s[i] - '0';
if (a[i].c == 0) {
a[i].c0++;
} else {
a[i].c1++;
}
}
LazySegmentTree<Info, Tag> seg(a);
for (int i = 0; i < m; i++) {
int o, l, r;
cin >> o >> l >> r;
l--;
if (o == 0) {
seg.rangeApply(l, r, 1);
} else {
cout << seg.rangeQuery(l, r).c1 << '\n';
}
}
return 0;
}
B
原题题面错误。
题面重制
七夕节左近,楚楚想去见女朋友,可是他最近和女朋友吵架了,女朋友躲着他,不知道会出现在哪座城市里。楚楚心知肚明女朋友是在赌气,所以无论自己在哪座城市,女朋友在哪座城市,他一定要在七夕节见到她。城市之间用铁路或者城际公交中的一种相连通,虽然并不是任意两个城市都直接相连,但是保证可以通过这两种交通方式从任一城市出发到另一任意城市。由于楚楚的特殊身份,他可以免费乘坐城际公交,那么他最少需要买多少张火车票才能保证见到女朋友呢?输入描述:
第一行三个整数 ,表示共 个城市,编号从 到 , 条城际公交线, 条铁路。
接下来 行,每行两个整数 ,表示城市 之间可以通过城际公交相互到达。
再接下来 行,每行两个整数 ,表示城市 之间可以通过铁路相互到达。
实际是构造最小生成树,城际公交免费即直接连边。
。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
#define range(a) begin(a), end(a)
struct UnionFind {
int n;
vector<int> f, sz;
UnionFind(const int &n = 0) : n(n), f(n), sz(n, 1) {
iota(f.begin(), f.end(), 0);
}
int get(int x) {
while (x != f[x]) {
x = f[x] = f[f[x]];
}
return x;
}
bool unite(int x, int y) {
x = get(x), y = get(y);
if (x != y) {
f[y] = x;
sz[x] += sz[y];
return 1;
}
return 0;
}
bool united(int x, int y) {
return get(x) == get(y);
}
int size(int x) {
x = get(x);
return sz[x];
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, k, m;
cin >> n >> k >> m;
UnionFind f(n);
for (int i = 0; i < k; i++) {
int u, v;
cin >> u >> v;
u--, v--;
f.unite(u, v);
}
vector<array<int, 2>> e(m);
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
u--, v--;
e[i] = {u, v};
}
int ans = 0;
for (int i = 0; i < m; i++) {
auto &[u, v] = e[i];
if (f.unite(u, v)) {
ans++;
}
}
cout << ans << '\n';
return 0;
}
C
。
https://www.luogu.com.cn/problem/P1006
D
数据水。
懒标记线段树,区间修改,区间查询最小值。
。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
template <class Info, class Tag>
struct LazySegmentTree {
int n;
vector<Info> info;
vector<Tag> tag;
LazySegmentTree() : n(0) {}
LazySegmentTree(int n_, Info v_ = Info()) {
init(n_, v_);
}
template<class T>
LazySegmentTree(vector<T> init_) {
init(init_);
}
void init(int n_, Info v_ = Info()) {
init(vector(n_, v_));
}
template<class T>
void init(vector<T> init_) {
n = init_.size();
info.assign(4 << __lg(n), Info());
tag.assign(4 << __lg(n), Tag());
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);
}
template<class F>
int findFirst(int p, int l, int r, int x, int y, F pred) {
if (l >= y || r <= x || !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 || !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);
}
};
struct Tag {
int x;
Tag(const int &x = 0) : x(x) {};
void apply(const Tag &t) {
x += t.x;
}
};
struct Min {
int x;
Min(const int &x = 1E9) : x(x) {}
void apply(const Tag &t) {
x += t.x;
}
};
Min operator+(const Min &a, const Min &b) {
return min(a.x, b.x);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
LazySegmentTree<Min, Tag> seg(a);
for (int i = 0; i < m; i++) {
int d, s, t;
cin >> d >> s >> t;
s--;
if (seg.rangeQuery(s, t).x < d) {
cout << "-1\n" << i + 1 << '\n';
return 0;
}
seg.rangeApply(s, t, -d);
}
cout << "0\n";
return 0;
}
E
原题数据错误。
无向有环图最长路。
可以 。
F
队友写的 。
G
模拟。
复杂度不会算。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
#define range(a) begin(a), end(a)
struct P {
pair<int, int> p;
P() {}
P(const string &s) {
string x, y;
for (auto &si : s) {
if (si >= 'a' && si <= 'z') {
x += si;
} else {
y += si;
}
}
if (x == "heitao") {
p.second = 4;
} else if (x == "hongtao") {
p.second = 3;
} else if (x == "meihua") {
p.second = 2;
} else if (x == "fangkuai") {
p.second = 1;
}
if (y == "A") {
p.first = 1;
} else if (y == "J") {
p.first = 11;
} else if (y == "Q") {
p.first = 12;
} else if (y == "K") {
p.first = 13;
} else {
p.first = stoi(y);
}
}
bool operator<(const P &t) const {
return p < t.p;
}
};
struct F {
pair<int, vector<P>> p;
F() {}
F(const vector<P> &v) {
p.second = v;
int sum = 0;
for (int i = 0; i < 5; i++) {
sum += min(10, v[i].p.first);
}
p.first = -1;
for (int i = 0; i < 5; i++) {
for (int j = i + 1; j < 5; j++) {
for (int k = j + 1; k < 5; k++) {
int x = min(10, v[i].p.first);
int y = min(10, v[j].p.first);
int z = min(10, v[k].p.first);
if ((x + y + z) % 10 == 0) {
int w = (sum - x - y - z) % 10;
w += (w == 0 ? 10 : 0);
p.first = max(p.first, w);
}
}
}
}
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<vector<P>> a(n, vector<P>(5));
vector<F> b(n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < 5; j++) {
string s;
cin >> s;
a[i][j] = P(s);
}
sort(range(a[i]), [&](P &a, P &b) {
return a.p > b.p;
});
b[i] = F(a[i]);
}
vector<int> p(n);
iota(range(p), 0);
sort(range(p), [&](int &i, int &j) {
return b[i].p > b[j].p;
});
cout << p[0] << '\n';
return 0;
}
H
可以使用双向队列。
https://www.luogu.com.cn/problem/P1016
I
https://www.luogu.com.cn/problem/P1069
J
,答案即为从 出发到其他点的最长路。
。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
template <class T>
T max(const vector<T> &a) {
return *max_element(a.begin(), a.end());
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, k;
cin >> n >> k;
vector<vector<int>> g(n);
for (int i = 0; i < n; i++) {
g[i].push_back((i + 1) % n);
g[i].push_back((i + k) % n);
}
queue<int> q;
vector<int> dis(n, -1);
q.push(0);
dis[0] = 0;
while (!q.empty()) {
auto cur = q.front();
q.pop();
for (auto &nex : g[cur]) {
if (dis[nex] == -1) {
q.push(nex);
dis[nex] = dis[cur] + 1;
}
}
}
cout << max(dis) << '\n';
return 0;
}
K
表。
。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
template <class T>
struct SparseTable {
int n;
vector<vector<T>> a;
SparseTable(const vector<T> &init) : n(init.size()) {
int lg = __lg(n);
a.assign(lg + 1, vector<T>(n));
a[0] = init;
for (int i = 1; i <= lg; i++) {
for (int j = 0; j <= n - (1 << i); j++) {
a[i][j] = min(a[i - 1][j], a[i - 1][(1 << (i - 1)) + j]);
}
}
}
T get(int l, int r) {// [l, r)
int lg = __lg(r - l);
return min(a[lg][l], a[lg][r - (1 << lg)]);
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
SparseTable<int> mn(a);
for (int i = 0; i + m <= n; i++) {
cout << mn.get(i, i + m) << '\n';
}
return 0;
}