枚举每个元素\(a_i\),通过\(lower\_bound\)找到\(b\)中第一个大于等于\(a_i\)的元素的下标\(j\),然后取\(min(|a_i-b_j|,|a_i-b_{j-1}|)\)。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 5;
const int INF = 0x3f3f3f3f;
int a[MAXN], b[MAXN] = {INF};
int main(int argc, char *argv[]) {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; ++i) cin >> a[i];
for (int i = 1; i <= m; ++i) cin >> b[i];
sort(b + 1, b + m + 1);
int res = INF;
for (int i = 1; i <= n; ++i) {
int j = lower_bound(b + 1, b + m + 1, a[i]) - b;
res = min({res, abs(b[j] - a[i]), abs(a[i] - b[j - 1])});
}
cout << res << '\n';
system("pause");
return 0;
}
D - Querying Multiset
本题没有区间查询的操作,所以可以不用线段树等数据结构来实现,我们考虑用优先队列的方法,维护一个\(add\)标记,表示队列中的数增加的值。
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main(int argc, char *argv[]) {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
priority_queue<int, vector<int>, greater<int>> Q;
int q;
cin >> q;
int add = 0;
while (q--) {
int opt, x;
cin >> opt;
switch (opt) {
case 1:
cin >> x;
Q.push(x - add); // 因为队列中的数默认是+add的, 所以新入队的元素要-add
// 如果不减add, 考虑一个元素刚入队就出队的情况, 那它就变成了x+add
break;
case 2:
cin >> x;
add += x;
break;
default:
cout << Q.top() + add << '\n';
Q.pop();
break;
}
}
system("pause");
return 0;
}
E - Safety Journey
因为题目给定的是完全图并且不能走的边至多有\(5000\),所以我们可以反向思考,只存无法到达的边。
考虑动态规划的解法:
\(dp[i][j]\)表示第\(i\)天在\(j\)点的方案数。
\(dp[i][j] = sum - \sum_{v}^{n} dp[i-1][v](sum表示上一天所有的方案数的和,v表示无法从j到达的点)\)
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 5e3 + 5;
const int MOD = 998244353;
int dp[MAXN][MAXN];
vector<int> e[MAXN];
signed main(int argc, char *argv[]) {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n, m, k;
cin >> n >> m >> k;
for (int i = 1; i <= n; ++i) {
e[i].push_back(i);
}
while (m--) {
int u, v;
cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
}
dp[0][1] = 1;
int prev = 1; // 上一天所有方案数的和
for (int i = 1; i <= k; ++i) {
int cur = 0;
for (int u = 1; u <= n; ++u) {
dp[i][u] = prev;
for (int v: e[u]) {
dp[i][u] = (dp[i][u] - dp[i - 1][v] + MOD) % MOD;
}
cur = (cur + dp[i][u]) % MOD;
}
prev = cur;
}
cout << dp[k][1] << '\n';
system("pause");
return 0;
}