目录
C:冶炼金属![](https://i-blog.csdnimg.cn/blog_migrate/9ab3158586a1df5e504cf4464e2aed2e.png)
推公式或者二分, 下面是二分做法
#include<iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int mx = 1e9, mn = 0;
for (int i = 1; i <= n; i ++ ) {
int a, b;
cin >> a >> b;
mx = min(mx, a / b);
int l = 0, r = mx;
while (l < r) {
int mid = l + r + 1 >> 1;
if (mid * (b + 1) < a) l = mid;
else r = mid - 1;
}
while (l * (b + 1) <= a) l ++ ;
mn = max(mn, l);
}
cout << mn << ' ' << mx << endl;
return 0;
}
D:飞机降落
【评测用例规模与约定】 对于 30% 的数据,N ≤ 2。 对于 100% 的数据,1 ≤ T ≤ 10,1 ≤ N ≤ 10,0 ≤ Ti , Di , Li ≤ 105。
根据数据范围和时间限制, T * 10!= 3,628,8000 暴力枚举降落顺序即可(可以采用暴搜或者
next_permutation() 函数暴力枚举)
注意:贪心排序是错误做法,因为可以最晚降落时间可以很长,但是可以骗取一定分数
下面是dfs代码
#include<iostream>
#include<cstring>
using namespace std;
int t[20], d[20], l[20];
int n, m;
bool st[20];
bool dfs(int u, int s) {
if (u > n) return true;
for (int i = 1; i <= n; i ++ ) {
if (!st[i]) {
st[i] = true;
if (t[i] + d[i] >= s) {
if (dfs(u + 1, max(t[i] + l[i], s + l[i]))) return true;
}
st[i] = false;
}
}
return false;
}
void solve() {
memset(st, 0, sizeof st);
cin >> n;
for (int i = 1; i <= n; i ++ ) cin >> t[i] >> d[i] >> l[i];
if (dfs(1, 0)) cout << "YES" << endl;
else cout << "NO" << endl;
}
int main()
{
int t;
cin >> t;
while (t -- ) {
solve();
}
return 0;
}
E:接龙数列
【评测用例规模与约定】 对于 20% 的数据,1 ≤ N ≤ 20。 对于 50% 的数据,1 ≤ N ≤ 10000。 对于 100% 的数据,1 ≤ N ≤ 105,1 ≤ Ai ≤ 109。所有 Ai 保证不包含前导 0。
数据范围很大,采用O(n) 或者 O(nlogn) 做法,但是观察发现首位数和末尾数只有10种,采用线性dp即可,时间复杂度O(n)
#include <iostream>
using namespace std;
int f[10];
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i ++) {
string s;
cin >> s;
int m = s.size();
f[s[m - 1] - '0'] = max(f[s[m - 1] - '0'], f[s[0] - '0'] + 1);
}
int res = 0;
for (int i = 0; i < 10; i ++ )
res = max(res, f[i]);
cout << n - res;
return 0;
}
F:岛屿个数![](https://i-blog.csdnimg.cn/blog_migrate/79ccd674d60d49dfc894ea4eb0abe3de.png)
俩遍BFS
第一遍 BFS, 从(0, 0)开始扩展, 把所有能扩展到的岛屿标记
第二遍 BFS, 把所有被标记的岛屿的联通岛屿找出来计数即可
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <numeric>
#include <set>
#include <map>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#define x first
#define y second
#define endl '\n'
#define NOCOM std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0)
#define rge(i, x, y) for (int i = x; i <= y; i ++ )
// #define int long long
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
constexpr int N = 1e5 + 10;
bool st[60][60], ok[60][60];
char mp[60][60];
int n, m;
int dx[8] {0, 1, 0, -1, - 1, - 1, 1, 1}, dy[] {1, 0, -1, 0, -1, 1, -1, 1};
void bfs() {
queue<PII> q;
q.push({0, 0});
while (q.size()) {
auto [x, y] = q.front();
q.pop();
rge(i, 0, 7) {
int px = x + dx[i], py = y + dy[i];
if (px < 0 || py < 0 || px > n + 1 || py > m + 1) continue;
if (mp[px][py] == '0' && !st[px][py]) q.push({px, py});
st[px][py] = true;
}
}
}
void solve() {
memset(st, 0, sizeof st);
memset(ok, 0, sizeof ok);
cin >> n >> m;
rge(i, 0, n + 1) rge(j, 0, m + 1) mp[i][j] = '0';
rge(i, 1, n) rge(j, 1 ,m) cin >> mp[i][j];
bfs();
int res = 0;
auto GetTog = [&](int i, int j) -> void {
queue<PII> q;
q.push({i, j}), ok[i][j] = true;
while (q.size()) {
auto [x, y] = q.front();
q.pop();
rge(i, 0, 3) {
int px = x + dx[i], py = y + dy[i];
if (px < 1 || py < 1 || px > n || py > m) continue;
if (mp[px][py] == '1' && !ok[px][py])
q.push({px, py}), ok[px][py] = true;
}
}
};
rge(i, 1, n) rge(j, 1, m)
if (st[i][j] && !ok[i][j] && mp[i][j] == '1')
GetTog(i, j), res ++ ;
cout << res << endl;
}
signed main() {
NOCOM;
int t;
cin >> t;
rge(i, 1, t) solve();
return 0;
}
G: 子串简写
这题比之前几题简单
O(n)做法采用前缀和
O(nlogn)做法采用二分计算即可
下面是二分代码:
注意:二分有边界问题,对vector判断是否为空,防止CE
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int k;
char a, b;
string s;
cin >> k >> s >> a >> b;
vector<int> p;
int n = s.size();
long long res = 0;
for (int i = 0; i < n; i ++ ) {
if (s[i] == a) p.push_back(i);
if (s[i] == b && p.size()) {
int l = 0, r = p.size() - 1;
while (l < r) {
int mid = l + r >> 1;
if (p[mid] >= i - k + 1) r = mid;
else l = mid + 1;
}
if (p[l] > i - k + 1) {
if (l != 0) res += l;
} else res += l + 1;
}
}
cout << res << endl;
return 0;
}
H: 整数删除
数据结构题,采用数组模拟链表+平衡树或者优先队列模拟即可
#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <numeric>
#include <set>
#include <map>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#define x first
#define y second
#define endl '\n'
#define NOCOM std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0)
#define rge(i, x, y) for (int i = x; i <= y; i ++ )
#define int long long
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
constexpr int N = 5e5 + 10;
int n, m, a[N];
int ne[N], pre[N], idx = 1, h = 1;
set<PII> st;
void solve() {
cin >> n >> m;
rge(i, 1, n) cin >> a[i];
rge(i, 1, n) {
pre[i] = i - 1, ne[i] = i + 1;
st.insert({a[i], i});
}
auto erase = [&](int idx, int v) -> void {
st.erase({a[pre[idx]], pre[idx]});
st.erase({a[ne[idx]], ne[idx]});
a[pre[idx]] += v, a[ne[idx]] += v;
ne[pre[idx]] = ne[idx], pre[ne[idx]] = pre[idx];
if (ne[idx] <= n) st.insert({a[ne[idx]], ne[idx]});
if (pre[idx] > 0) st.insert({a[pre[idx]], pre[idx]});
if (idx == h) h = ne[idx];
};
while (st.size() > n - m) {
auto [v, idx] = *(st.begin());
erase(idx, v);
st.erase({v, idx});
}
for (int i = h; i <= n; i = ne[i])
cout << a[i] << " \n"[ne[i] > n];
}
signed main() {
NOCOM;
int t = 1;
// cin >> t;
rge(i, 1, t) solve();
return 0;
}
I: 景区导游
LCA,倍增求LCA即可
#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <numeric>
#include <climits>
#include <set>
#include <map>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#define x first
#define y second
#define endl '\n'
#define NOCOM std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0)
#define rge(i, x, y) for (int i = x; i <= y; i ++ )
#define int long long
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
constexpr int N = 1e5 + 10;
int n, m;
vector<PII> h[N];
void solve() {
cin >> n >> m;
rge(i, 1, n - 1) {
int a, b, c;
cin >> a >> b >> c;
h[a].emplace_back(b, c);
h[b].emplace_back(a, c);
}
vector<int> a(m + 1), dh(n + 1, INT_MAX), dt(n + 1);
vector<vector<int>> f(n + 1, vector<int>(21));
rge(i, 1, m) cin >> a[i];
auto bfs = [&]() -> void {
queue<int> q;
q.push(1), dh[1] = 1, dh[0] = 0;
while (q.size()) {
int u = q.front();
q.pop();
for (auto [x, v] : h[u]) {
if (dh[x] > dh[u] + 1) {
// cout << u << ' ' << x << ' ' << v << endl;
dh[x] = dh[u] + 1;
dt[x] = dt[u] + v;
f[x][0] = u;
q.push(x);
rge(i, 1, 20) f[x][i] = f[f[x][i - 1]][i - 1];
}
}
}
};
bfs();
auto get = [&](int a, int b) -> int {
if (dh[a] < dh[b]) swap(a, b);
int len = dt[a] + dt[b];
for (int i = 20; i >= 0; i -- )
if (dh[f[a][i]] >= dh[b]) a = f[a][i];
if (a == b) return len - dt[a] * 2;
for (int i = 20; i >= 0; i -- )
if (f[a][i] != f[b][i])
a = f[a][i], b = f[b][i];
return len - dt[f[a][0]] * 2;
};
int s = 0;
rge(i, 2, m) s += get(a[i], a[i - 1]);
rge(i, 1, m) {
if (i == 1) cout << s - get(a[1], a[i + 1]) << ' ';
else if (i == m) cout << s - get(a[m - 1], a[m]) << endl;
else cout << s - get(a[i - 1], a[i]) - get(a[i + 1], a[i]) + get(a[i - 1], a[i + 1]) << ' ';
}
}
signed main() {
NOCOM;
int t = 1;
// cin >> t;
rge(i, 1, t) solve();
return 0;
}