Manthan, Codefest 18

本鸽对着鸽笼发四,直到北京站结束,绝对不会咕掉一场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类型的数组,意外意外)

猜你喜欢

转载自blog.csdn.net/qq_38759433/article/details/82389862
今日推荐