本鸽对着鸽笼发四,直到北京站结束,绝对不会咕掉一场cf
好久没打了,然后喜闻乐见,A题被安排了,读错题了,求的是袋子数,我以为是硬币数,然后对着空气推了1h。意识到错误后,nc地认为复杂度是O(n),没敢写循环,求了个等比数列前n项和,然后取log,pp,之后喜闻乐见被精度fst了。之后B又鼓捣了半小时,还wa了一发,C倒是很顺利,10min解决。后面的题就没时间写了
A
打表可以发现:1,2,4,8,16,32,64...
#include <bits/stdc++.h>
using namespace std;
int main(){
int tot = 1, n;
cin >> n;
int ans = 0;
while(tot < n){
n -= tot;
tot *= 2;
ans ++;
}
cout << ans + 1 << endl;
return 0;
}
B
显然,需要先把中间的数加成需要的数,然后分别向左向右迭代更改数值即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[200200];
int main(){
ll ans = 0;
ll n, s;
cin >> n >> s;
for(ll i = 0; i < n; i ++)
cin >> a[i];
sort(a, a + n);
ll pos = n / 2;
ll val = abs(a[pos] - s);
ans = val;
a[pos] = s;
for(ll i = pos - 1; i >= 0; i --){
if(a[i] > a[i + 1]){
ans += a[i] - a[i + 1];
a[i] = a[i + 1];
}
}
for(int i = pos + 1; i < n; i ++){
if(a[i] < a[i - 1]){
ans += a[i - 1] - a[i];
a[i] = a[i - 1];
}
}
/*for(ll i = 0; i < n; i ++)
cout << a[i] << ' ';
cout << endl;*/
cout << ans << endl;
return 0;
}
C
不难发现,只有当两个数距离为1时交换他们才可能比另一种方案优秀
#include <bits/stdc++.h>
using namespace std;
bool vis[1001000];
char a[1001000], b[1001000];
int main(){
int n;
cin >> n;
scanf("%s", a);
scanf("%s", b);
for(int i = 0; i < n; i ++){
if(a[i] != b[i]){
vis[i] = true;
}
}
long long ans = 0;
for(int i = 1; i < n; i ++){
if(vis[i] && vis[i - 1] && a[i] != a[i - 1]){
vis[i] = vis[i - 1] = false;
ans ++;
}
}
for(int i = 0; i < n; i ++){
if(vis[i])
ans ++;
}
cout << ans << endl;
return 0;
}
D
先搞清楚可行的情况:当前这个数属于树的这一层。
于是,在bfs的过程中将每一层的结点存起来然后再判断即可。这就会遇到一些问题:
1、如何知道当前在哪一层。当该层结点个数为0时说明该层结束,应该到下一层了
2、如何知道目前扩展到了哪一层。当从一个结点往外扩展,遇到一个新结点时就说明这是新的一层的。
另外,因为要快速插入删除某个元素,所以用了set(话说竟然还能开set类型的数组,意外意外)