• Codeforces Round #703 Div.2 A B C1 C2 D


    完整题单

    我终于要补题了,因为我发现稳定过三题还是难.

    以后打算把Div.2的千人题都尽力补了.

    A

    交了一次WA了后发现漏读一个只能从i到i+1的条件,最后写了个模拟,挺费事的,正解是拿前缀和不停地和公式比较.

    B

    货舱选址问题,熟悉,一发入魂.

    C1,C2

    止步于此,太弱了.

    一开始自作聪明写了个假的二分,完全没有意识到复杂度不对劲,不停地WA.

    直接说C2的算法(也能通过C1),先在1~n中找到第二大的数的位置pos,然后看看1~pos中第二大是不是还是pos,如果是说明最大在1~pos-1,否则在pos+1~n,那么分类讨论,二分求解这两个范围.

    边界条件就是pos==1,2,n-1,n,而只需要ask()里判断一下就可以了,感觉不是很容易想到.

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    int n;
    
    int ask(int x, int y) {
        if (x >= y) return -1;
        cout << "? " << x << ' ' << y << endl;
        cout.flush();
        int ret;
        cin >> ret;
        return ret;
    }
    
    int main() {
        cin >> n;
        int pos = ask(1, n);
        if(ask(1, pos) == pos){        // on the left
            int l = 1, r = pos - 1;
            while(l < r){
                int mid = l + r + 1 >> 1;
                if(ask(mid, pos) == pos) l = mid;
                else r = mid - 1;
            }
            cout << "! " << l << endl;
        }else{
            int l = pos + 1, r = n;
            while(l < r){
                int mid = l + r >> 1;
                if(ask(pos, mid) == pos) r = mid;
                else l = mid + 1;
            }
            cout << "! " << l << endl;
        }
    
        return 0;
    }
    C2

     D

     对于一个有序序列中的一个数,想要知道它是不是中位数,只需要关心不小于他的数和比他小的数的数量.

    如果想要一个有序序列的中位数是否不小于于x,只需要看不小于x的数是否达到序列长度的一半.

    后者是一个以x为自变量的具有单调性的问题,使用二分答案求解.

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    int n, k, s[200010];
    int pre[200010];
    
    bool check(int x){
        for(int i = 1; i <= n; i++){
            if(s[i] >= x) pre[i] = 1;
            else pre[i] = -1;
            pre[i] += pre[i - 1];
        }
    
        int small = 0;
        for(int i = k; i <= n; i++){
            small = min(small, pre[i - k]);
            if(pre[i] - small > 0) return true;
        }
        return false;
    }
    
    int main() {
        cin >> n >> k;
        for(int i = 1; i <= n; i++) cin >> s[i];
    
        int l = 1, r = n;
        while(l < r){
            int mid = l + r + 1 >> 1;
            if(check(mid)) l = mid;
            else r = mid - 1;
        }
    
        cout << l << endl;
    
        return 0;
    }
    D

    最后发现B是中位数,C是二分,D是中位数与二分.

  • 相关阅读:
    90. 子集 II
    274. H 指数
    1291. 顺次数
    StreamWriter 跟BinaryWriter的区别
    非常有用的正则表达式
    linux菜单恢复
    VS2008的诡异问题
    一些常用算法 练手的的代码
    string 类型为空的处理方法
    left jion 的多表连接用法。
  • 原文地址:https://www.cnblogs.com/Gaomez/p/14418076.html
Copyright © 2020-2023  润新知