OVSolitario-io

导航

联合训练

1.Educational Codeforces Round 183
A:取模

B:贪心

思路有点问题,感谢队友教学

对于问题,关注整体而不是过程,即对于操作,重要的不是操作,而是采用操作发生了什么,带来什么影响,以及多个状态叠加影响(确定优先级)对局面的转变

关注那些起始状态,中间状态,最终状态,甚至是极端状态

点击查看代码
//关注0,1,2操作发现0/1会造成确定-
//对于2(不确定)来说:讨论2与x(n - (0/1)的大小关系)
//x > 2:变为?即可
//x <= 2:转变为-
while(_ -- ) {
    cin >> n >> k;
    cin >> s;
    int a, b, c;
    a = count(s.begin(), s.end(), '0'), 
    b = count(s.begin(), s.end(), '1'), 
    c = count(s.begin(), s.end(), '2');
    
    string ans(n, '+');
    for(int i = 0; i < n; ++ i) {
        if(i < a + c || i > n - 1 - b - c) ans[i] = '?';
        if(k == n || i < a || i > n - 1 - b) ans[i] = '-';//n=k时一定可删全部
    }
    cout << ans  << "\n";
}

C:贪心
通过转化将ab串转化为1/-1(对偶)串,总和为0时则ab相等

计算当前数组的总和 𝑠,要使总和等于 0 ,必须删除总和为 𝑠的一个数段
(问题就简化为找出总和为 𝑠的最短线段)

采用前缀和,遍历线段的右边界,求每个和为𝑠的最短线段 (l <= r, prefr+1 - prefl = s),即prefr+1 - s = prefl

注意取值范围-n~n,存储空间为2*n数组(采用x+n记录),或者使用map结构

点击查看代码
int cur = count(s.begin(), s.end(), 'a') - 
count(s.begin(), s.end(), 'b');//总和

map<int, int> mp;//前缀和及位置
int pr = 0;
mp[pr] = -1;

ans = n;
for(int i = 0; i < n; ++ i) {
    pr += s[i] == 'a' ? 1 : -1;
    mp[pr] = i;//更新pr位置求全局
    if(mp.count(pr - cur)) {//求[l,i]存在cur
        ans = min(ans, i - mp[pr - cur]);
    }
}
cout << (ans == n ? -1 : ans) << "\n";

posted on 2025-10-14 08:21  TBeauty  阅读(1)  评论(0)    收藏  举报