Educational Codeforces Round 184 (Div. 2)

A. Alice and Bob

根据题目要求,Bob要想得分最大化就是要使Bob能够得分的球尽可能得多。

通过 lower_bound 函数和 upper_bound(这是因为题目中说平局也就是数组中的元素与a一样大是使Alice得分,我们要避免与a相同) 函数分别得到 比 a 小和比 a 的元素的数量,紧接着就是分类讨论,如果 left 比 right 要多,则让b = a - 1,则左边的数更接近与 b ,否则让 b=a + 1.

void solve(){
    int n, a;
    cin >> n >> a;
    vector<int> v(n + 1);
    for(int i = 1; i <= n; ++i) cin >> v[i];
    int left =lower_bound(v.begin() + 1, v.end(), a) - v.begin();
    int right = upper_bound(v.begin() + 1, v.end(), a) - v.begin();
    if(left - 1 >= (n -  right + 1)){
        cout << a - 1 << endl;
    }else{
        cout << a + 1 << endl;
    }
    return ;
}

B. Drifting Away

多花点时间枚举一些情况就行了。"**"、"*<"、">*"、"><" 这四种情况可以无限航行,只要字符串中出现这样的组合输出-1就行。

排除无限航行的情况后就是计算最长的航行时间了,"<<<<<*>>"、"<<<<<>>>>",要航行到岸边,要么字符串左边存在连续的"<",要么字符串右侧出现连续的">",那么我们记两个指针left 和 right,一个从左往右记录有多少个"<",一个从右往左记录有多少">"。遍历完成后就可以进行比较了。如果遍历结束后left 和 right 的位置有 "*",那可以从 "*"开始走增加航行时间,分类讨论下就行。

void solve(){
    string s;
    cin >> s;
    int len = s.length();
    for(int i  = 0; i < len - 1; ++i){
        if(s[i] == '*'){
            if(s[i + 1] == '*' || s[i + 1] == '<'){
                cout << -1 << endl;
                return ;
            }
        }else if(s[i] == '>'){
            if(s[i + 1] == '<'  || s[i + 1] == '*'){
                cout << -1 << endl;
                return ;
            }
        }
    }

    int l = 0, r = len - 1;
    int cnt0 = 0, cnt1 = 0;
    while(s[l] == '<' && l < len) {
        l++;
        cnt0++;
    }
    while(s[r] == '>' && r >= 0){
        r--;
        cnt1++;
    }
    if((s[l] == '*' || s[r] == '*') && l < len && r >= 0){
        cout  << max(cnt0, cnt1) + 1 << endl;
    }else{
        cout << max(cnt0, cnt1) << endl;
    }
    return ;
}

C. Range Operation

image

根据题目可以推出上述等式,其中res表示数组前缀和。只要保证 F(R) - F(L-1) 最大就行,逐个遍历一遍就行,每次尽可能得取 F(L-1) 的最小值就行

void solve(){
    int n;
    cin >> n;
    vector<int> a(n + 1);
    int sum = 0;
    for(int i = 1; i <= n; ++i) {
        cin >> a[i];
        sum += a[i];
    }
    vector<int> res(n + 1, 0);
    for(int i = 1; i <= n; ++i){
        res[i] = res[i - 1] + a[i];
    }

    vector<int> f(n + 1, 0);
    for(int i = 1; i <= n; ++i){
        f[i] = i * i + i - res[i];
    }
    int minn = MAX;
    int t = 0;
    for(int i = 0;i <= n; ++i){
        minn = min(minn, f[i]);
        t = max(t, f[i] - minn);
    }
    cout << t + sum << endl;
    return ;
}

D1. Removal of a Sequence (Easy Version)

通过题目可以知道每次都会删除第 y 的倍数的数字,求第k个数是什么。那我们这样想,如果经过 x 次删除后正好剩 k 个数,那么这第 k 个数就应该是未经过x次删除的原数的个数

那么这样就好想了,每次枚举数的数量,经过 x 次删除后判断是否有 k 个数,二分答案。

假设原数的个数为 p ,每次会删除 y 的倍数,那么每次删除就还剩 p -= p - [p / y] 个数,以此为二分的判断依据。

void solve(){
    
    cin >> x >> y >> k;
    int l = 1, r = 1e12;
    int ans = -1;
    while(l <= r){
        int mid = l + r >> 1;
        if(check(mid)){
            l = mid + 1;
        }else{
            ans = mid;
            r = mid - 1;
        } 
    }
    cout << ans << endl;
}
posted @ 2025-11-26 00:54  菜鸡の编程日常  阅读(28)  评论(0)    收藏  举报