[hdu6757]Hunting Monsters
关于打怪兽的顺序,有经典结论:
优先打a<b的怪兽,这些怪兽按a从小到大,其余怪兽按b从大到小
(证明调整法即可,具体略)
将所有怪兽以此法排序,则打怪兽的顺序总是从前往后
对于a<b的怪兽,当确定答案后,总是贪心打一个前缀
同时,显然答案单调不降,因此前缀长度也单调不降
对于a≥b的怪兽,定义fi,j表示[i,n]中打j只怪兽的最小体力,转移即
fi,j=min
若(f_{i+1,j-1}\le )f_{i+1,j}\le b_{i}(\le a_{i}),根据递推式,显然f_{i,j}=f_{i+1,j}\le b_{i}
求出最小的j满足f_{i+1,j}\le b_{i},则[0,j]中均不变,\{b_{i}\}\cup (j,n]即对前一项+(a_{i}-b_{i})取\max
归纳\{b_{i}\}\cup (j,n]上凸,则上述操作即在斜率中加入a_{i}-b_{i}并重新排序
另外,对其的操作即增加b_{i}和删除第二个元素起比b_{i}小的元素,显然均保持凸性
根据凸性,使用优先队列维护斜率,合并时根据前者决策单调性分治即可
时间复杂度为o(n\log n),可以通过
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 300005 4 #define mod 1000000007 5 #define ll long long 6 #define pii pair<int,int> 7 #define fi first 8 #define se second 9 int t,n,na,nb,ans,x[N],y[N];ll sum[N],fa[N],fb[N],f[N]; 10 pii a[N],b[N];priority_queue<ll>q; 11 void solve(int l,int r,int x,int y){ 12 if (l>r)return; 13 int mid=(l+r>>1); 14 for(int i=x;i<=y;i++) 15 if ((i<=mid)&&(mid-i<=nb))f[mid]=min(f[mid],max(fa[i],fb[mid-i]-sum[i])); 16 for(int i=x;i<=y;i++) 17 if ((i<=mid)&&(mid-i<=nb)&&(f[mid]==max(fa[i],fb[mid-i]-sum[i]))){ 18 solve(l,mid-1,x,i),solve(mid+1,r,i,y); 19 return; 20 } 21 } 22 int main(){ 23 scanf("%d",&t); 24 while (t--){ 25 scanf("%d",&n),na=nb=0; 26 for(int i=1;i<=n;i++)scanf("%d",&x[i]); 27 for(int i=1;i<=n;i++)scanf("%d",&y[i]); 28 for(int i=1;i<=n;i++){ 29 if (x[i]<y[i])a[++na]=make_pair(x[i],y[i]); 30 else b[++nb]=make_pair(-y[i],x[i]); 31 } 32 sort(a+1,a+na+1),sort(b+1,b+nb+1); 33 for(int i=1;i<=nb;i++)b[i]=make_pair(b[i].se,-b[i].fi); 34 for(int i=1;i<=na;i++){ 35 sum[i]=sum[i-1]+(a[i].se-a[i].fi); 36 fa[i]=max(fa[i-1],a[i].fi-sum[i-1]); 37 } 38 for(int i=nb,j=0;i;i--){ 39 ll now=b[i].se; 40 if (!q.empty()){ 41 ll s=q.top(); 42 q.pop(),q.push(s-b[i+1].se+b[i].se); 43 } 44 while ((!q.empty())&&(now-q.top()<=b[i].se))now-=q.top(),fb[++j]=now,q.pop(); 45 if (!q.empty())now-=q.top(),q.pop(),q.push(b[i].se-now); 46 q.push(b[i].se-b[i].fi); 47 if (i==1){ 48 ll now=b[i].se; 49 while (!q.empty())now-=q.top(),fb[++j]=now,q.pop(); 50 } 51 } 52 memset(f,0x3f,sizeof(f)); 53 ans=0,solve(0,n,0,na); 54 for(int i=1;i<=n;i++)ans=(ans+f[i]%mod*i)%mod; 55 printf("%d\n",ans); 56 } 57 return 0; 58 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步