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';
}