

(cf补题链接)[https://codeforces.com/gym/606649 ↗]
H#
题目描述#
给定三个数组, , ,长度分别为 , , ,每个数组取一个数求和,输出前个最大值。
数据范围: , ,
解题思路#
首先想到的最简单的思路是暴力求解,这样的时间复杂度将会是 ,如何优化呢?
我们可以将其中两个数组合并,这里我们选择将 两个数组合并,然后进行排序,这里复杂度为, 我么选择合并后的前个最大值和数组合并,这里的复杂度为, 可以用堆维护个数。
参考代码#
#include<bits/stdc++.h>
using i128 = __int128;
#define endl '\n'
#define int long long
#define pii std::pair<int ,int>
#define fix(x) std::fixed << std::setprecision(x)
const int inf = 1e17 + 50, MAX_N = 1e5 + 50, mod = 1e9 + 7;
void solve() {
int n, m, p, k;
std::cin >> n >> m >> p >> k;
std::vector<int> a(n), b(m), c(p);
for(int i = 0; i < n; i++) std::cin >> a[i];
for(int i = 0; i < m; i++) std::cin >> b[i];
for(int i = 0; i < p; i++) std::cin >> c[i];
std::vector<int> ab;
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
ab.push_back(a[i] + b[j]);
}
}
std::sort(ab.begin(), ab.end(), std::greater<>());
std::sort(c.begin(), c.end(), std::greater<>());
std::priority_queue<int, std::vector<int>, std::greater<> > pq;
for(int i = 0; i < std::min(k, (int) ab.size()); i++) {
for(int j = 0; j < p; j++) {
int t = ab[i] + c[j];
if (pq.size() == k) {
auto w = pq.top();
if (w < t) {
pq.pop();
pq.push(t);
}
} else {
pq.push(t);
}
}
}
std::vector<int> res;
while (!pq.empty()) {
res.push_back(pq.top());
pq.pop();
}
std::reverse(res.begin(), res.end());
for(auto i : res) {
std::cout << i << endl;
}
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr), std::cout.tie(nullptr);
solve();
return 0;
}
cppE#
题目描述#
给定一个长度为的数组, 有次询问,每次给出, 对于每次询问,我们要输出中在区间段 中,的数的个数。
数据范围:
解题思路#
赛时,我想的是对区间内的数排序,然后二分查找边界,计算数量,奈何
TLE
,tql,显然是排序超时了。
正解是树状数组或者线段树
参考代码#
#include<bits/stdc++.h>
using i128 = __int128;
#define int long long
#define endl '\n'
#define pii std::pair<int ,int>
#define fix(x) std::fixed << std::setprecision(x)
const int inf = 1e17 + 50, MAX_N = 1e5 + 50, mod = 1e9 + 7;
std::mt19937_64 rng(std::chrono::system_clock::now().time_since_epoch().count());
std::vector<int> a(MAX_N);
struct Node {
int l{}, r{};
std::vector<int> sorted;
};
Node tr[4 * MAX_N];
void build(int u, int l, int r) {
tr[u].l = l;
tr[u].r = r;
tr[u].sorted.clear();
if (l == r) {
tr[u].sorted.push_back(a[l]);
return;
}
int mid = (l + r) / 2;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
auto &left = tr[u << 1].sorted;
auto &right = tr[u << 1 | 1].sorted;
tr[u].sorted.resize(left.size() + right.size());
merge(left.begin(), left.end(), right.begin(), right.end(), tr[u].sorted.begin());
}
int query(int u, int l, int r, int start, int end) {
if (tr[u].r < l || tr[u].l > r) {
return 0;
}
if (l <= tr[u].l && tr[u].r <= r) {
auto &v = tr[u].sorted;
int left_pos = lower_bound(v.begin(), v.end(), start) - v.begin();
int right_pos = upper_bound(v.begin(), v.end(), end) - v.begin();
return right_pos - left_pos;
}
return query(u << 1, l, r, start, end) + query(u << 1 | 1, l, r, start, end);
}
void solve() {
int N, Q;
std::cin >> N >> Q;
for(int i = 1; i <= N; ++i) {
std::cin >> a[i];
}
build(1, 1, N);
while (Q--) {
int l, r, s, e;
std::cin >> l >> r >> s >> e;
std::cout << query(1, l, r, s, e) << endl;
}
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr), std::cout.tie(nullptr);
solve();
return 0;
}
cpp