Codeforces Round #796 (Div2) A~F题解
https://codeforces.com/contest/1688
打的稀碎,就不说结果了
A题
题意:
给定一个正整数,找到最小的正整数,使得,。
思路:
要使得, 显然要至少有一个二进制位相同。
要使得, 显然要至少有一个二进制位不同。
在此基础上找到最小的即可。
void solve() {
int x;
cin >> x;
int res = x & (-x);
if(res == x) {
for(int i = 0 ; i <= 30 ; i ++) {
if(!(res & (1 << i))) {
res |= (1 << i);
break;
}
}
}
cout << res << "\n";
}
B题
题意:
给定一个数组,希望用最少的操作代价,使得中所有元素均为奇数。可选操作为:
花费的代价,将中两个元素合并为它们的和。
花费的代价,将一个偶数元素的值变为原来的一半。
思路:
这个sb题我都能wa两发,太菜了。
如果数组中有奇数的话,显然我直接将所有偶数合并,然后再加个奇数,就没有偶数了。
如果数组中全为偶数的话,我优先把除二次数最小就能变成奇数的偶数变成奇数,然后同上操作即可。
int a[N];
void solve() {
int n;
cin >> n;
for(int i = 1 ; i <= n ; i ++) cin >> a[i];
int s = 0, res = 0;
int mind = 1e9;
for(int i = 1 ; i <= n ; i ++){
if((a[i] & 1) == 0) // 偶数的话
{
res ++;
int cnt = 0;
while(a[i] && (a[i] & 1) == 0) {
cnt ++;
a[i] >>= 1;
}
mind = min(mind, cnt);
}
}
if(res == n) res = res - 1 + mind;
cout << res << "\n";
}
C题
题意:
初始时有一个长度为的由小写字母组成的字符串。
它进行了次操作,每次操作选择的一个子串和任意字符串。
将中的子串替换成。现在乱序给出这个操作对应的两个字符串,以及最终字符串。
求出初始的。保证答案存在且唯一。
思路:
这个题真的是一点思路都没有,还是后面参考了别人的题解,才写的。
我只能说太女少了!
int cnt[30];
void solve() {
memset(cnt, 0, sizeof cnt);
int n;
cin >> n;
for(int i = 1 ; i <= n * 2 + 1 ; i ++) {
string s;
cin >> s;
for(auto c : s) cnt[c - 'a'] ++;
}
for(int i = 0 ; i < 26 ; i ++)
if(cnt[i] & 1){
cout << (char)(i + 'a') << "\n";
return;
}
}
D题
题意:
给定一个数组,可以选择任意下标为起点。然后按顺序执行以下操作次:
当前坐标为,可以改变下标为的三者之一。
获取对应下标的值,让。
整个数组值+1。
思路:
显然,当的时候,我们只需要找出长度为的最大连续子段和
然后再
当的时候,那么首先整个数组的值肯定能取到,那么怎么走能获得最多的自增值呢?
很容易发现,我们呆在数组一端原地不走,等到的时候再开始向另一端走就可以得到最大值。
int a[N];
void solve() {
int n, k;
cin >> n >> k;
for(int i = 1 ; i <= n ; i ++) cin >> a[i];
int maxv = 0, s = 0;
int l = 1;
for(int i = 1 ; i <= n ; i ++) {
s += a[i];
if(i - l + 1 > k) s -= a[l ++];
maxv = max(maxv, s);
}
int res = maxv;
if(k <= n) res += k * (k - 1) / 2;
else {
int p = k - 1;
int c = p - n + 1;
res += p * (p + 1) / 2 - c * (c + 1) / 2 + c;
}
cout << res << "\n";
}
E题
题意:
交互题。有一个无向图有个点,和条边,但是这个图为止(即不知道边怎么连的)。
现在可以进行至多次查询,然后求出这个无向图的最小权值完全生成森林。
即生成森林连通分量个数和无向图一样多,边权和最小。
每次可以询问一个长度为的串。代表包含这条边。
系统回应由这些边组成的无向图的最大生成森林的值。
思路:
通过次询问,每次只包含一条边,那么我们可以获得所有边的长度。
然后对边进行排序之后,按照kruskal的思想,我们每次加入一条边查询来判断一条边是否能加入后改变连通性,这样查询次就能得到答案。
char s[N];
pii edge[N];
bool cmp(pii a, pii b){
return a.x < b.x;
}
void solve() {
int n, m;
cin >> n >> m;
for(int i = 0 ; i < m ; i ++) s[i] = '0';
for(int i = 0 ; i < m ; i ++) {
s[i] = '1';
cout << "? " << s << endl;
int len;
cin >> len;
edge[i] = {len, i};
s[i] = '0';
}
sort(edge, edge + m, cmp);
int minv = 0;
for(int i = 0 ; i < m ; i ++) {
int l = edge[i].x, now = edge[i].y;
s[now] = '1';
cout << "? " << s << endl;
int len;
cin >> len;
if(minv + l == len) minv = len;
else s[now] = '0';
}
cout << "! " << minv << endl;
}
F题
题意:
给定两个长度为的数组, ,以及个区间。
每次操作可以选择一个满足的区间,让这个区间对应位置变成对应位置的值。
问能够通过若干次操作将变成。能输出,否则输出。
思路:
令,为的前缀和。
那么区间操作合法等价于。
如果操作区间都不相交,那么我们直接进行合法操作,操作完判断即可。
对一个区间的操作,效果就是使得
也即
现在的问题是区间很可能是相交的,它们之间互相是有影响的,前面的操作可能会导致后面无法操作。
对于上面这两个区间。如果操作第一个区间,那么它会导致第二个区间。
如果操作第二个区间,那么它会导致第一个区间。
最终肯定是要所有的都成立。
我们如果选取的 ,那么事实上是没有什么意义的。
因为我们并没有使任何的,反而可能导致一些操作无法进行。
因此我们必然是选择 的区间进行操作。
而对于这些区间,操作的顺序是没有关系的。
int a[N];
int b[N];
int c[N];
int s[N];
void solve() {
int n, m;
cin >> n >> m;
for(int i = 1 ; i <= n ; i ++) cin >> a[i];
set<int> st;
// 两个数组一样,等价于差数组 c 的前缀和数组 s 全为 0
for(int i = 1 ; i <= n ; i ++) {
cin >> b[i];
c[i] = a[i] - b[i];
s[i] = s[i - 1] + c[i];
if(s[i]) st.insert(i); // 如果当前点还未置零 放入set中
}
queue<pii> que; // 用于保存所有将执行操作的区间
vector<vector<pii>> v(n + 1);
for(int i = 1 ; i <= m ; i ++) {
int l, r;
cin >> l >> r;
if(!s[l - 1] && !s[r]) que.push({l, r});
else {
v[l - 1].push_back({l, r});
v[r].push_back({l, r});
}
}
while(!que.empty()) {
auto u = que.front();
que.pop();
auto iter = st.lower_bound(u.x); // 操作区间的起点
while(iter != st.end() && *iter <= u.y) {
s[*iter] = 0;
for(auto ints : v[*iter]) { // 查看一下那些线段,有一端在当前操作区间的 ,置零后是否可以操作了
if(!s[ints.x - 1] && !s[ints.y]) { // 可以操作了就放进队列里
que.push(ints);
}
}
st.erase(iter ++); // 删除当前点,该点已置零
}
}
if(st.empty()) { // 所有点已经置零
cout << "YES\n";
} else {
cout << "NO\n";
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)