zoukankan      html  css  js  c++  java
  • 2018-2019 ICPC焦作区域赛B

    本题解借鉴了某大佬的博客,由于那篇博客里有点小错误,因此我这里重写一篇,希望大家在看到我的博客的同时也关注一下那位大佬。
    大佬博客地址

    题目链接

    题解思路:很显然,要使奥特曼受到的伤害最小,肯定要先杀死一只怪兽,所以我们就分类讨论先杀A还是先杀B。

    //不少人可能会说比较一下A,B的攻击力,先杀攻击力高的一定会更优。但这是错误的,比如一个100血10攻的怪和一只3血9攻的怪,显然是要先杀3血9攻的那只怪。

    因此,我们就分类先杀A还是先杀B,然后比较两者的耗费和字典序,取最小即可。

    首先处理一个前缀和的数组pri[i]表示1到i时刻的伤害总和。

    1.先杀A

    我们先算出最快打死A的回合:u1=lower_bound(pri+1,pri+100000,a.H)-pri
    打死两个怪的最快时间:u2=lower_bound(pri+1,pri+100000,a.H+b.H)-pri

    (1)哪怕不分A溢出的伤害,剩下的伤害也足以在u2-u1回合内打死B
    这样肯定是1-u1是A,u1+1到u2是B字典序最小。

    (2)pri[u2]-pri[u1]<b.H
    在这种情况下,A溢出的伤害必然要打到B上,那应该在那一次打呢?自然是尽可能靠后,B越靠后字典序越小。

    2.先杀B

    算出最快打死B的回合:u1=lower_bound(pri+1,pri+100000,b.H)-pri
    先杀B分伤害给A的情况处理起来就比较麻烦,因为要使A尽可能靠前,这里最好的情况就是在伤害值<=B溢出伤害时前面能插入一段连续的A,然后这段的伤害+pri[u2]-pri[u1]>=a.H,这样能保证B先死且A尽可能地靠前。可是如果不行呢,我们就只能把前面连续的A拆出来,往后移,让对A的伤害值变大,这样才能打死两只怪兽。

    (1)一段A的前缀+pri[u2]-pri[u1]>=a.H
    (2)在上述情况打不死的情况下,定义left=a.H-(pri[u2]-pri[u1]) (前面那部分所需要造成的伤害)。在1-u1的回合,当left>=2*i+1 || left==i 的时候插入A,left -= i,否则插入B,剩下的全是A。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define maxn 300005
    #define ll long long
    const int mod = 1e9 + 7;
    
    int T;
    ll pri[maxn];
    struct node{
        ll H,K;
    }a,b;
    
    void init(){
        for(int i=1;i<=1e5;i++)
            pri[i]=pri[i-1]+i;
    }
    
    int main()
    {
        init();
        scanf("%d",&T);
        while(T--){
            ll suma=0,sumb=0;
            string ansa,ansb;
            scanf("%lld %lld %lld %lld",&a.H,&b.H,&a.K,&b.K);
            //A先死-
            int u1=lower_bound(pri+1,pri+100000,a.H)-pri;
            int u2=lower_bound(pri+1,pri+100000,b.H+a.H)-pri;
            ll left=pri[u1]-a.H;
            suma=a.K*u1+b.K*u2;
            if(pri[u2]-pri[u1]>=b.H){
                for(int i=1;i<=u1;i++)
                    ansa+='A';
                for(int i=u1+1;i<=u2;i++)
                    ansa+='B';
            }
            else{
                for(int i=1;i<=u1;i++){
                    if(i==left)ansa+='B';
                    else ansa+='A';
                }
                for(int i=u1+1;i<=u2;i++)
                    ansa+='B';
            }
            //B先死
            u1=lower_bound(pri+1,pri+100000,b.H)-pri;
            u2=lower_bound(pri+1,pri+100000,a.H+b.H)-pri;
            sumb=b.K*u1+a.K*u2;
            left=pri[u1]-b.H;
            int pos=upper_bound(pri+1,pri+100000,left)-pri-1;
            if(pri[pos]+pri[u2]-pri[u1]>=a.H){
                for(int i=1;i<=pos;i++)
                    ansb+='A';
                for(int i=pos+1;i<=u1;i++)
                    ansb+='B';
                for(int i=u1+1;i<=u2;i++)
                    ansb+='A';
            }
            else{
                left=a.H-(pri[u2]-pri[u1]);
                for(int i=1;i<=u1;i++){
                    if(left>=2*i+1||left==i){
                        left-=i;
                        ansb+='A';
                    }
                    else ansb+='B';
                }
                for(int i=u1+1;i<=u2;i++)
                    ansb+='A';
            }
            if(suma<sumb)cout<<suma<<" "<<ansa<<"
    ";
            else if(sumb<suma)cout<<sumb<<" "<<ansb<<"
    ";
            else{
                if(ansa<ansb)cout<<suma<<" "<<ansa<<"
    ";
                else cout<<sumb<<" "<<ansb<<"
    ";
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    leetcode75 Sort Colors
    leetcode74 Search a 2D Matrix
    岭南职业技术学院清远大学城网
    南华工商学院大学城网
    清远职业技术学院大学城网
    大学城网清远
    清远学城网
    Android 华为手机物理键盘挡住了我的应用底部导航栏
    Android 性能优化之-(ViewStub)
    Android程序员必读之书
  • 原文地址:https://www.cnblogs.com/Mmasker/p/11917466.html
Copyright © 2011-2022 走看看