• Codeforces Round #681 (Div. 2, based on VK Cup 2019-2020


    Codeforces Round #681 (Div. 2, based on VK Cup 2019-2020 - Final)

    传送门

    B

    题意:01串,消去连续的1费用为a,将一个0变成1费用为b,问消除所有1的最低费用。

    题解:对于每段连续1计算与前一个段的距离len,如果费用len*b<a,选择把一段0变成1,否则直接消去连续的1。

    #include<iostream>
    using namespace std;
    int t,a,b;
    string s;
    int main(){
        cin>>t;
        while(t--){
            cin>>a>>b;
            cin>>s;
            int p=0;
            for(int i=0;i<s.length();i++){
                if(s[i]=='1'){
                    p=i;
                    break;
                }
            }
            int ans=0,ok=0,len=1e5+7;
            for(int i=p;i<s.length();i++){
                if(s[i]=='1'){
                    if(ok==0){
                        ans+=min(a,len*b);
                        ok=1;
                        len=0;
                    }
                }
                if(s[i]=='0'){
                    ok=0;
                    len++;
                }
            }
            printf("%d
    ",ans);
        }
    }
    
    

    C

    题意:n个菜,可以自己做,也可以点外卖,自己做要a[i]时间,点外卖b[i]时刻送达,最快最久完成n道菜。(自己做累加时间,点外卖取最长时间)

    题解:对于一个某个菜我选择点外卖假如10分钟送达,如果另一个菜点外卖的话9分钟送达,那么我肯定两个菜都点外卖,因为第二个菜不会占用我任何时间,那么我们对外卖的送达时间排序按小到大排序,枚举前i个菜都点外卖的情况,后n-i个菜自己做(用前缀和优化)的时间,更新ans。

    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define ll long long
    int t,n;
    struct madoka{
        ll a;
        ll b;
    }ma[200007];
    ll pre[200007];
    bool cmp(madoka a1,madoka a2){
        if(a1.a==a2.a){
            return a1.b>a2.b;
        }
        else{
            return a1.a<a2.a;
        }
    }
    int main(){
        cin>>t;
        while(t--){
            cin>>n;
            for(int i=1;i<=n;i++){
                cin>>ma[i].a;
            }
            for(int i=1;i<=n;i++){
                cin>>ma[i].b;
            }
            sort(ma+1,ma+1+n,cmp);
            pre[n+1]=0;
            for(int i=n;i>=1;i--){
                pre[i]=pre[i+1]+ma[i].b;
            }
            ll ans=1e18+7;
            for(int i=0;i<=n;i++){
                ans=min(ans,max(ma[i].a,pre[i+1]));
            }
            printf("%lld
    ",ans);
        }
    }
    
    

    D

    题意:n个数,每次可以选择前或后若干个数都减一,问能否全0;

    题解:对于一个递减序列,我当然能完成

    ​ 如:5 4 3 2 2 >> 4 4 3 2 2 >> 3 3 3 2 2 >> 2 2 2 2 2 >> 0 0 0 0 0 ;

    只要把前一个变成于后一个一样,之后再一起减1就好了。(递增同理)

    ​ 先递减再递增也当然可以,拆开同上操作即可,问题就是,无峰函数怎么判断是否合法,其实也不难,首先先找前第一段递减区间,同上操作,剩下的区间我只需考虑如何尽可能让它递增即可,在区间的值不能增加情况下,让区间尽可能递增,只能让尽可能让每一个位置的前一个位置的值尽可能小。

    ​ 如:6 5 4 5 4 5 3

    ​ 找到递减区间 654,

    ​ 那么省下5 4 5 3,我就让前一个位置值尽可能小,5最多可跟着前面的值减4,到1。

    ​ 省下 1 4 5 3,前一个位置减了4,但要满足递增,4最多减3,到1,

    ​ 省下 1 1 5 3,前位置减了3,5可以减3,到2,

    ​ 省下 1 1 2 3,最后序列递增输出YES,否则NO。

    #include<iostream>
    using namespace std;
    int t,n,a[30007];
    int main(){
        cin>>t;
        while(t--){
            cin>>n;
            for(int i=1;i<=n;i++){
                cin>>a[i];
            }
            int p=n,now=0,ok=1;
            for(int i=2;i<=n;i++){
                if(a[i]>a[i-1]){
                    p=i;
                    now=a[i-1];
                    a[i]-=now;
                    break;
                }
            }
            for(int i=p+1;i<=n;i++){
                if(a[i]<a[i-1]){
                    ok=0;
                }
                else{
                    int lin=a[i]-a[i-1];
                    now=min(lin,now);
                    a[i]-=now;
                }
            }
            if(ok)printf("YES
    ");
            else{
                printf("NO
    ");
            }
        }
    }
    

  • 相关阅读:
    一个故事看懂CPU的SIMD技术
    MySQL 表数据多久刷一次盘?
    java高级用法之:无所不能的java,本地方法调用实况
    java高级用法之:调用本地方法的利器JNA
    网络协议之:socket协议详解之Datagram Socket
    网络协议之:socket协议详解之Socket和Stream Socket
    netty系列之:java中的base64编码器
    网络协议之:socket协议详解之Unix domain Socket
    git 常用命令
    在线curl转换
  • 原文地址:https://www.cnblogs.com/whitelily/p/13917387.html
Copyright © 2020-2023  润新知