• CCPC-Wannafly Winter Camp Day4 Div1


    题目链接:https://zhixincode.com/contest/18/problem/I?problem_id=267

    题目描述

    输入描述

     

    输出描述

    一行一个整数表示答案。

    样例输入 1

    3
    20 1
    15 10
    20 2

    样例输出 1

    60

    题解:

    首先肯定的是,这 $n$ 次选择必然是分为两段的,前一段全部是召唤,后一段全部是加攻。

    然后我们只需要考虑,这两段的数目即可,然后我们假设这个函数和最后的总攻击力是一个单峰函数,就可以上三分。

    那么接下来考虑在确定多少张牌召唤,多少张牌加攻的前提下,怎么安排顺序:

    因为生物数目是确定的 $x$,所以我们可以知道一张牌它如果 $b cdot x - a$ 越大,把它选成加攻击力就更赚,因此可以排个序后确定哪些牌是召唤、哪些牌是加攻,从而最终确定总攻击力。

    最后的时间复杂度就是 $O(log_{1.5}n cdot n cdot log_{2} n)$。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    #define a(p) (p.first)
    #define b(p) (p.second)
    const int maxn=1e5+5;
    
    int n,x;
    P c[maxn];
    inline bool cmp(const P& u,const P& v) {
        return b(u)*x-a(u)<b(v)*x-a(v);
    }
    ll check(int mid)
    {
        x=mid, sort(c+1,c+n+1,cmp);
        ll res=0;
        for(int i=1;i<=n;i++) res+=(i<=x)?a(c[i]):b(c[i])*x;
        return res;
    }
    
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0), cout.tie(0);
    
        cin>>n;
        for(int i=1;i<=n;i++) cin>>a(c[i])>>b(c[i]);
        int l=0, r=n; ll ans=0;
        while(l<=r)
        {
            if(r-l<=10)
            {
                for(int i=l;i<=r;i++) ans=max(ans,check(i));
                break;
            }
            int lmid=l+(r-l)/3, rmid=l+(r-l)*2/3;
            ll lres=check(lmid), rres=check(rmid);
            if(lres<=rres) l=lmid;
            else r=rmid;
        }
        cout<<ans<<endl;
    }
  • 相关阅读:
    递归
    排序算法的稳定性与复杂度总结
    二分查找
    希尔排序
    快速排序
    归并排序
    插入排序
    选择排序
    冒泡排序
    i2c_smbs 函数
  • 原文地址:https://www.cnblogs.com/dilthey/p/10407528.html
Copyright © 2020-2023  润新知