[ABC203F]Weed

[ABC203F]Weed

壹、题目描述 ¶

传送门 to Atcoder.

贰、题解 ¶

注意到 Takahashi 最多只会拔 \(\log a\) 次,我们可以考虑将 \(a\) 排序之后,设计状态 \(f_{i,j}\) 表示拔完前 \(i\) 草,其中 Takahashi 拔了 \(j\) 次后,Aoki 的最小拔草次数。

转移显而易见,对于最后的答案,我们从小到大枚举 Takahashi 的操作次数,如果 \(f_{i,j}\le k\),那么操作 \(\lang j,f_{i,j}\rang\) 就是合法的答案。

时间复杂度 \(\mathcal O(n\log n)\).

叁、参考代码 ¶

#include<cstdio>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;

// #define NDEBUG
#include<cassert>

namespace Elaina{
    #define rep(i, l, r) for(int i=(l), i##_end_=(r); i<=i##_end_; ++i)
    #define drep(i, l, r) for(int i=(l), i##_end_=(r); i>=i##_end_; --i)
    #define fi first
    #define se second
    #define mp(a, b) make_pair(a, b)
    #define Endl putchar('\n')
    #define mmset(a, b) memset(a, b, sizeof a)
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef pair<ll, ll> pll;
    template<class T>inline T fab(T x){ return x<0? -x: x; }
    template<class T>inline void getmin(T& x, const T rhs){ x=min(x, rhs); }
    template<class T>inline void getmax(T& x, const T rhs){ x=max(x, rhs); }
    template<class T>inline T readin(T x){
        x=0; int f=0; char c;
        while((c=getchar())<'0' || '9'<c) if(c=='-') f=1;
        for(x=(c^48); '0'<=(c=getchar()) && c<='9'; x=(x<<1)+(x<<3)+(c^48));
        return f? -x: x;
    }
    template<class T>inline void writc(T x, char s='\n'){
        static int fwri_sta[1005], fwri_ed=0;
        if(x<0) putchar('-'), x=-x;
        do fwri_sta[++fwri_ed]=x%10, x/=10; while(x);
        while(putchar(fwri_sta[fwri_ed--]^48), fwri_ed);
        putchar(s);
    }
}
using namespace Elaina;

const int maxn=2e5;
const int loga=30;

int a[maxn+5], n, k;
int f[maxn+5][loga+5];

signed main()
{
    n=readin(1), k=readin(1);
    rep(i, 0, n-1) a[i]=readin(1);
    sort(a, a+n);
    memset(f, 0x3f, sizeof f);
    rep(j, 0, loga) f[0][j]=0;
    for(int i=0; i<n; ++i){
        int cur=upper_bound(a, a+n, a[i]>>1)-a;
        rep(j, 0, loga) getmin(f[i+1][j+1], f[cur][j]);
        rep(j, 0, loga) getmin(f[i+1][j], f[i][j]+1);
    }
    rep(j, 0, loga) if(f[n][j]<=k)
        return writc(j,' '), writc(f[n][j]), 0;
    return 0;
}

肆、关键的地方 ¶

注意这种每次操作 \(x\over 2\) 的题,一般都要考虑是不是最多 \(\log\) 个回合。

然后就我们可以设计状态将这个放到维度上面去了。

posted @ 2021-06-03 17:03  Arextre  阅读(58)  评论(0编辑  收藏  举报