yuwj  

CF global round 29

C

思路:

只要考虑每个 0 的位置怎么更新

考虑从当前 pos[i] 转移到下一个 pos[i+1] 的位置

分三种情况,

中间没有 1, 只要当前位置有一个位置左右两种情况都能转移

中间 1 个 1, 必须让左右两个 0,看向中间这个 1 才行

中间 1 的数量 > 1, 强制前一个0向左,后一个 0 向右才可行

再考虑初始化和最终状态的结果情况,就是看要不要强制方向

初始化第一个 0,左边有 1,就必须向右看

最后一个0,后面有 1,就必须向左看,答案就是 dpL

否则两边都可行,答案就是 dpL | dpR

代码:

void Solve(){
	cin >> n >> s, s = " " +s;
	vector<int> pos;
	For(i,1,n) if(s[i] == '0') pos.pb(i);

	if(pos.empty()) return puts("YES"), void();
	m = pos.size();
	vector<int> dp0(m), dp1=dp0;
	
	int i0 = pos[0];
	if(i0 > 1 && s[i0-1] == '1'){
		dp1[0] = 1;
	}else{
		dp0[0] = dp1[0] = 1;
	}

	for(int i=0;i<m-1;++i){
		l = pos[i], r = pos[i+1];
		int mid = r-l-1, ndp0 = 0, ndp1 = 0;
		if(mid == 0){
			if(dp0[i] || dp1[i]) ndp0 = ndp1 = 1;
		}else if(mid == 1){
			if(dp0[i]) ndp1 = 1;
			if(dp1[i]) ndp0 = 1;
		}else{
			if(dp0[i]) ndp1 = 1; 
		}
		dp0[i+1] = ndp0, dp1[i+1] = ndp1;
	}

	bool ok = 0;
	int ik = pos.back();
	if(ik<n && s[ik+1] == '1'){
		ok |= dp0[m-1];
	}else{
		ok |= (dp1[m-1] || dp0[m-1]);
	}

	puts(ok?"YES":"NO");
}

D

这个是SB题吧,什么东西啊看,比A还简单啊

这个场到底什么难度

就肯定是选频次最多的,然后奇数换先手,完了,后手不跟必挂

void Solve(){
	cin >> n;
	map<int,int> cnt;
	For(i,1,n) cin >> x, cnt[x]++;
	
	vector<pii> todo;
	for(auto [num,cc] : cnt) todo.emplace_back(num,cc);
	sort(all(todo), [&](pii a,pii b){
		if(a.second == b.second) return a.first > b.first;
		return a.second > b.second;
	});

	ll ans[2]{}, now = 0;
	for(auto [x, ncnt] : todo){
		ans[now] += 1ll * (x+1)/2 * ncnt, ans[now^1] += 1ll * x/2 * ncnt;
		if(x&1) now ^= 1;
	}

	cout << ans[0] << ' ' << ans[1] << '\n';
}
posted on 2025-09-21 17:34  xiaowang524  阅读(28)  评论(0)    收藏  举报