HDU 6469 /// 二分

題目大意:c++

分裂怪有1到n種等級,ide

第1級的分裂怪稱爲原子怪,它不會分裂,被擊殺時會產生a[1]點經驗;spa

而第k級的分裂怪死亡時則會分裂成a[k]個第k - 1級的分裂怪。code

一個體力能夠殺死一個怪物。blog

q個詢問,每次給定一個整體力值,求最多能得到多少經驗it

 

二分消滅的1級怪的個數,不斷向上合併,能達到n級怪就是可行的event

合併中應該向上取整class

假設 1個i級怪會分裂成3個i+1級怪,此時若i+1級怪消滅了5個,則至少應消滅2個i級怪基礎

如有連續不少級別的怪物只會分裂成1個怪物 那麼就會出現一條長鏈 cli

把這一整條長鏈合併成一個點 記錄下這個點離合並了多少個點就能夠計算體力值的耗費了

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LL long long
#define inc(i,j,k) for(int i=j;i<=k;i++)
#define dec(i,j,k) for(int i=j;i>=k;i--)
#define gcd(i,j) __gcd(i,j)
#define mem(i,j) memset(i,j,sizeof(i))
const int N=1e5+5;
const int mod=1e9+7;

int n,q,tot;
LL v[N],s[N];

bool check(LL m,LL w) {
    int sum=n; // 還須要消滅sum個級別的怪物才能得到經驗
    inc(i,1,tot) {
        if(m==1) return (w-sum)>=0;
        // 在消滅低級怪M個的基礎上
        // 此時必須消滅當前級別的m個怪物
        // 剩餘體力還有w 到第n級還有sum個級別
        sum-=v[i]; w-=m*v[i];
        if(i<tot) m=m/s[i+1]+(m%s[i+1]==0 ? 0:1); // 向上取整
        if(w<0) return 0; // 體力不夠 無解
    }
    return 1;
}

int main()
{
    scanf("%d%d",&n,&q);
    tot=1; v[tot]=1LL;
    scanf("%lld",&s[tot]);
    inc(i,2,n) {
        LL t; scanf("%lld",&t);
        if(t==1) v[tot]++;
        else v[++tot]=1, s[tot]=t;
        // 把只能分裂1個低級怪的怪物鏈合起來
    }
    while(q--) {
        LL w; scanf("%lld",&w);
        LL L=0,R=(LL)1e9,ans=0;
        while(L<=R) {
            LL M=(L+R)>>1;
            if(check(M,w)) ans=M, L=M+1;
            else R=M-1;
        } // 二分一共能打倒的一級怪的個數
        printf("%lld\n",ans*s[1]);
    }

    return 0;
}
View Code
相關文章
相關標籤/搜索