CodeForces Round #959 sponsored by NEAR (Div. 1 + Div. 2) 补题记录(A~E)
简单场.png
A
若
时间复杂度
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 500100;
int a[233][233];
signed main() {
int T;
cin >> T;
while (T--) {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
cin >> a[i][j];
if (n == 1 && m == 1)
puts("-1");
else {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
int v;
if (j != m) v = a[i][j + 1];
else if (i != n) v = a[i + 1][1];
else v = a[1][1];
cout << v << ' ';
}
cout << '\n';
}
}
}
return 0;
}
B
手模几组数据之后可以发现:
- 若两个字符串已经相等则一定成立。
- 若两个字符串不相等,则令
串中第一个是 的位置 , 串中第一个是 的位置 。若有 则有解,否则无解。
时间复杂度为
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 500100;
int a[233][233];
signed main() {
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
string s, t;
cin >> s >> t;
if (s == t)
puts("Yes");
else {
for (int i = 0; i < n; ++i) {
if (s[i] == '1') {
puts("Yes");
break;
} else if (t[i] == '1') {
puts("No");
break;
}
}
}
}
return 0;
}
C
简单 dp 题。正着做不好处理,考虑倒着做。
设
- 若
则 。 - 若
则 。 - 否则令
为最小的满足 的位置 。则有 。
前面两个转移都是容易的,第三个转移直接维护一下前缀和,然后二分找到
时间复杂度为
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 500100;
int a[N], s[N], f[N];
signed main() {
int T;
cin >> T;
while (T--) {
int n, x;
cin >> n >> x;
for (int i = 1; i <= n; ++i)
cin >> a[i], s[i] = s[i - 1] + a[i];
f[n + 1] = f[n + 2] = 0;
int sum = 0;
for (int i = n; i; --i) {
int l = i, r = n, best = -1;
while (l <= r) {
int mid = l + r >> 1;
if (s[mid] - s[i - 1] <= x)
best = mid, l = mid + 1;
else
r = mid - 1;
}
if (best == -1)
sum += (f[i] = f[i + 1]);
else
sum += (f[i] = best - i + 1 + f[best + 2]);
}
cout << sum << '\n';
}
return 0;
}
D
考虑倒着处理。首先若
然后对于剩下的一些倍数关系。若当前枚举的倍数关系为
时间复杂度为
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 500100;
int a[N], fa[N];
vector<int> b[N];
int find(int x) {
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
signed main() {
srand(time(0));
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> a[i], fa[i] = i;
map<int, int> mp;
vector<pair<int, int>> res;
for (int i = 1; i <= n; ++i) {
if (mp.count(a[i])) {
int t = mp[a[i]], v = i;
res.emplace_back(t, v);
fa[find(t)] = find(v);
}
else
mp[a[i]] = i;
}
for (int i = n - 1 - res.size(); i; --i) {
for (int j = 0; j < i; ++j)
b[j].clear();
for (int j = 1; j <= n; ++j)
b[a[j] % i].emplace_back(j);
for (int j = 0; j < i; ++j)
for (int k = 1; k < b[j].size(); ++k) {
int A = b[j][0], B = b[j][k];
if (find(A) != find(B)) {
fa[find(A)] = find(B);
res.emplace_back(A, B);
goto ee;
}
}
ee:;
}
reverse(res.begin(), res.end());
if (res.size() == n - 1) {
puts("Yes");
for (auto &[u, v] : res)
cout << u << ' ' << v << '\n';
} else {
puts("NO");
}
}
return 0;
}
E
首先每一次可以挪动一个树的任意一个叶子结点,这样每一次操作树的大小都会减去一。因此一个大小为
此时可以发现,若对于两个树满足它们的大小分别为
然后考虑贪心。因为是位运算所以考虑按位处理答案。设当前枚举到了第
问题是这样贪心有可能并不优秀。例如说只有一个大小为
则通过删除任意两个叶子结点操作获得
此时考虑反悔贪心。直接在树上获取
时间复杂度为
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1000100;
int a[N];
signed main() {
srand(time(0));
ios_base::sync_with_stdio(0);
cin.tie(0);
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
for (int j = 1; j < a[i]; ++j) {
int t;
cin >> t;
}
}
sort(a + 1, a + n + 1);
int bit = 0;
for (int i = 20; ~i; --i) {
int id = -1;
for (int j = 1; j <= n; ++j)
if (a[j] >= (1ll << i)) {
bit |= (1ll << i);
a[j] -= (1ll << i);
id = j;
break;
}
if (~id && id != 1) {
for (int j = 1; j < id; ++j)
if (a[j] >= a[id]) {
int t = a[id];
for (int k = id; k > j; --k)
a[k] = a[k - 1];
a[j] = t;
break;
}
}
}
cout << bit << '\n';
}
return 0;
}
本文来自博客园,作者:yhbqwq,转载请注明原文链接:https://www.cnblogs.com/yhbqwq/p/18312872,谢谢QwQ
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)