HDU 6469 /// 二分
题目大意:
分裂怪有1到n种等级,
第1级的分裂怪称为原子怪,它不会分裂,被击杀时会产生a[1]点经验;
而第k级的分裂怪死亡时则会分裂成a[k]个第k - 1级的分裂怪。
一个体力可以杀死一个怪物。
q个询问,每次给定一个总体力值,求最多能获得多少经验
二分消灭的1级怪的个数,不断向上合并,能达到n级怪就是可行的
合并中应该向上取整
假设 1个i级怪会分裂成3个i+1级怪,此时若i+1级怪消灭了5个,则至少应消灭2个i级怪
若有连续很多级别的怪物只会分裂成1个怪物 那么就会出现一条长链
把这一整条长链合并成一个点 记录下这个点离合并了多少个点就可以计算体力值的耗费了
#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; }