VP Educational Codeforces Round 23
A. Treasure Hunt
题意:你要从
先看两个坐标的的距离能不能整除
点击查看代码
void solve() {
int x1, y1, x2, y2, x, y;
std::cin >> x1 >> y1 >> x2 >> y2 >> x >> y;
if ((x1 - x2) % x == 0 && (y1 - y2) % y == 0 && std::abs(x1 - x2) / x % 2 == std::abs(y1 - y2) / y % 2) {
std::cout << "YES\n";
} else {
std::cout << "NO\n";
}
}
B. Makes And The Product
题意:求数组选三个数有多少组是乘积最小的。
先从小到大排序,如果最小的出现超过三次,则答案为最小数里选两个的方案,如果最小的出现两次,答案为第二小的出现的次数,否则看第二小的数出现几次,类似的讨论。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
std::sort(a.begin(), a.end());
if (a[2] == a[0]) {
i64 cnt = std::count(a.begin(), a.end(), a[0]);
std::cout << cnt * (cnt - 1) * (cnt - 2) / 6 << "\n";
} else if (a[1] == a[0]) {
std::cout << std::count(a.begin(), a.end(), a[2]) << "\n";
} else if (a[2] == a[1]) {
i64 cnt = std::count(a.begin(), a.end(), a[2]);
std::cout << cnt * (cnt - 1) / 2 << "\n";
} else {
std::cout << std::count(a.begin(), a.end(), a[2]) << "\n";
}
}
C. Really Big Numbers
题意:求
一个数加一,其数位和最多加一,且最多加10次数位和就会减少若干个9。所以只有
点击查看代码
void solve() {
i64 n, s;
std::cin >> n >> s;
if (s > n) {
std::cout << 0 << "\n";
return;
}
for (i64 i = s; i <= n; ++ i) {
i64 x = i, sum = 0;
while (x) {
sum += x % 10;
x /= 10;
}
if (i - sum >= s) {
std::cout << n - i + 1 << "\n";
return;
}
}
std::cout << 0 << "\n";
}
D. Imbalanced Array
题意:求所有子数组的最大值减最小值的和。
求出每个数作为最大值的左右边界
可以用单调栈求
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n + 2);
for (int i = 1; i <= n; ++ i) {
std::cin >> a[i];
}
std::stack<std::pair<int, int>> stk;
a[0] = a[n + 1] = 1e9;
stk.push({a[0], 0});
std::vector<int> lmax(n + 2), rmax(n + 2);
for (int i = 1; i <= n + 1; ++ i) {
while (a[i] > stk.top().first) {
rmax[stk.top().second] = i - 1;
stk.pop();
}
lmax[i] = stk.top().second + 1;
stk.push({a[i], i});
}
while (stk.size()) {
stk.pop();
}
a[0] = a[n + 1] = -1e9;
stk.push({a[0], 0});
std::vector<int> lmin(n + 2), rmin(n + 2);
for (int i = 1; i <= n + 1; ++ i) {
while (a[i] < stk.top().first) {
rmin[stk.top().second] = i - 1;
stk.pop();
}
lmin[i] = stk.top().second + 1;
stk.push({a[i], i});
}
i64 ans = 0;
for (int i = 1; i <= n; ++ i) {
ans += (i64)a[i] * ((i64)(i - lmax[i] + 1) * (rmax[i] - i + 1) - (i64)(i - lmin[i] + 1) * (rmin[i] - i + 1));
}
std::cout << ans << "\n";
}
E. Choosing The Commander
题意:每次插入一个
用字典树维护每一位有多少数经过,那么对于一个查询,我们贴着
点击查看代码
const int N = 1e6 + 5;
int trie[N * 30][2];
int node_cnt[N * 30];
struct TrieWith01 {
int idx;
int creat() {
memset(trie[idx], 0, sizeof trie[idx]);
node_cnt[idx] = 0;
return idx ++ ;
}
TrieWith01() {
idx = 0;
creat();
}
void insert(int x) {
int p = 0;
for (int i = 29; i >= 0; -- i) {
int s = x >> i & 1;
if (!trie[p][s]) {
trie[p][s] = creat();
}
p = trie[p][s];
++ node_cnt[p];
}
}
void insert(int x, int v) {
int p = 0;
for (int i = 29; i >= 0; -- i) {
int s = x >> i & 1;
if (!trie[p][s]) {
trie[p][s] = creat();
}
p = trie[p][s];
node_cnt[p] += v;
}
}
int xor_max(int x) {
int p = 0;
int res = 0;
for (int i = 29; i >= 0; -- i) {
int s = x >> i & 1;
if (trie[p][!s]) {
res += 1 << i;
p = trie[p][!s];
} else {
p = trie[p][s];
}
}
return res;
}
int query_geq(int x, int k, bool eq = true) {
int p = 0;
int res = 0;
for (int i = 29; i >= 0; -- i) {
int a = x >> i & 1, b = k >> i & 1;
if (b == 1) {
p = trie[p][a ^ 1];
} else {
res += node_cnt[trie[p][a ^ 1]];
p = trie[p][a];
}
if (p == 0) {
break;
}
}
if (eq) {
res += node_cnt[p];
}
return res;
}
int query_leq(int x, int k, bool eq = true) {
int p = 0;
int res = 0;
for (int i = 29; i >= 0; -- i) {
int a = x >> i & 1, b = k >> i & 1;
if (b == 1) {
res += node_cnt[trie[p][a]];
p = trie[p][a ^ 1];
} else {
p = trie[p][a];
}
if (p == 0) {
break;
}
}
if (eq) {
res += node_cnt[p];
}
return res;
}
};
void solve() {
int q;
std::cin >> q;
TrieWith01 tr;
while (q -- ) {
int op, x, y;
std::cin >> op >> x;
if (op == 1) {
tr.insert(x, 1);
} else if (op == 2) {
tr.insert(x, -1);
} else {
std::cin >> y;
std::cout << tr.query_leq(x, y, false) << "\n";
}
}
}
F. MEX Queries
题意:
先把所有数离散化,那么我们可以用线段树维护区间值,懒标记维护
注意要把每个
点击查看代码
#define ls (u << 1)
#define rs (u << 1 | 1)
#define umid (tr[u].l + tr[u].r >> 1)
template <class Info, class Tag>
struct Node {
int l, r;
Info info;
Tag tag;
};
template <class Info, class Tag>
struct SegmentTreeWithLazy {
std::vector<Node<Info, Tag> > tr;
SegmentTreeWithLazy(int _n) {
init(_n);
}
SegmentTreeWithLazy(std::vector<Info> & a) {
int _n = (int)a.size() - 1;
init(_n, a);
}
void init(int _n) {
tr.assign(_n << 2, {});
build(1, _n);
}
void init(int _n, std::vector<Info> & a) {
tr.assign(_n << 2, {});
build(1, _n, a);
}
void pushup(int u) {
tr[u].info = tr[ls].info + tr[rs].info;
}
void pushdown(Node<Info, Tag> & u, Tag tag) {
u.info = u.info + tag;
u.tag = u.tag + tag;
}
void pushdown(int u) {
if (tr[u].tag.exist()) {
pushdown(tr[ls], tr[u].tag);
pushdown(tr[rs], tr[u].tag);
tr[u].tag.clear();
}
}
void build(int l, int r, int u = 1) {
tr[u] = {l, r, {}};
if (l == r) {
return;
}
int mid = l + r >> 1;
build(l, mid, ls); build(mid + 1, r, rs);
}
void build(int l, int r, std::vector<Info> & a, int u = 1) {
tr[u] = {l, r, {}};
if (l == r) {
tr[u].info = a[l];
return;
}
int mid = l + r >> 1;
build(l, mid, a, ls); build(mid + 1, r, a, rs);
pushup(u);
}
void modify(int l, int r, Tag tag, int u = 1) {
if (l <= tr[u].l && tr[u].r <= r) {
pushdown(tr[u], tag);
return;
}
pushdown(u);
int mid = umid;
if (l <= mid) {
modify(l, r, tag, ls);
}
if (r > mid) {
modify(l, r, tag, rs);
}
pushup(u);
}
Info query(int l, int r, int u = 1) {
if (l <= tr[u].l && tr[u].r <= r) {
return tr[u].info;
}
pushdown(u);
int mid = umid;
if (r <= mid) {
return query(l, r, ls);
} else if (l > mid) {
return query(l, r, rs);
}
return query(l, r, ls) + query(l, r, rs);
}
int query_first_not_appear(int u = 1) {
if (tr[u].l == tr[u].r) {
return tr[u].l;
}
pushdown(u);
int mid = umid;
if (tr[ls].info.sum != tr[ls].info.len) {
return query_first_not_appear(ls);
} else {
return query_first_not_appear(rs);
}
}
};
struct Info {
int sum, len;
};
struct Tag {
int set, rev;
bool exist() {
return set != -1 || rev != 0;
}
void clear() {
set = -1;
rev = 0;
}
};
Info operator + (const Info & a, const Info & b) {
Info res = a;
res.sum += b.sum;
res.len += b.len;
return res;
}
Info operator + (const Info & a, const Tag & b) {
Info res = a;
if (b.set != -1) {
res.sum = b.set * res.len;
}
if (b.rev) {
res.sum = res.len - res.sum;
}
return res;
}
Tag operator + (const Tag & a, const Tag & b) {
Tag res = a;
if (b.set != -1) {
res.set = b.set;
res.rev = 0;
}
res.rev ^= b.rev;
return res;
}
void solve() {
int n;
std::cin >> n;
std::vector<std::array<i64, 3>> op(n);
std::vector<i64> b;
for (int i = 0; i < n; ++ i) {
i64 t, l, r;
std::cin >> t >> l >> r;
op[i] = {t, l, r};
b.push_back(l);
b.push_back(r);
b.push_back(r + 1);
}
b.push_back(1);
std::sort(b.begin(), b.end());
b.erase(std::unique(b.begin(), b.end()), b.end());
int m = b.size();
auto get = [&](i64 x) -> int {
return std::lower_bound(b.begin(), b.end(), x) - b.begin() + 1;
};
std::vector<Info> info(m + 1);
for (int i = 1; i <= m; ++ i) {
info[i] = {0, 1};
}
SegmentTreeWithLazy<Info, Tag> tr(info);
for (auto & [t, L, R] : op) {
int l = get(L), r = get(R);
if (t == 1) {
tr.modify(l, r, Tag{1, 0});
} else if (t == 2) {
tr.modify(l, r, Tag{0, 0});
} else {
tr.modify(l, r, Tag{-1, 1});
}
std::cout << b[tr.query_first_not_appear() - 1] << "\n";
}
}
分类:
codeforces
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】