zoukankan      html  css  js  c++  java
  • 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是中位数与二分.

  • 相关阅读:
    Reactive Extensions (Rx) 入门(5) —— Rx的事件编程
    Reactive Extensions (Rx) 入门(4) —— Rx的事件编程
    Reactive Extensions (Rx) 入门(3) —— Rx的事件编程
    Reactive Extensions (Rx) 入门(2) —— 安装 Reactive Extensions
    Reactive Extensions (Rx) 入门(1) —— Reactive Extensions 概要
    Xamarin NuGet 缓存包导致 already added : Landroid/support/annotation/AnimRes 问题解决方案
    Android 系统Action大全
    Xamarin Forms 实现发送通知点击跳转
    如何理解灰度发布
    推荐一款分布式微服务框架 Surging
  • 原文地址:https://www.cnblogs.com/Gaomez/p/14418076.html
Copyright © 2011-2022 走看看