• [hdu6757]Hunting Monsters


    关于打怪物的顺序,有经典结论:

    优先打$a<b$的怪物,这些怪物按$a$从小到大,其余怪物按$b$从大到小

    (证明调整法即可,具体略)

    将所有怪物以此法排序,则打怪物的顺序总是从前往后

    对于$a<b$的怪物,当确定答案后,总是贪心打一个前缀

    同时,显然答案单调不降,因此前缀长度也单调不降

    对于$a\ge b$的怪物,定义$f_{i,j}$表示$[i,n]$中打$j$​只怪物的最小体力,转移即
    $$
    f_{i,j}=\min(f_{i+1,j},\min(f_{i+1,j-1}-b_{i},0)+a_{i})
    $$

    若$(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)$,可以通过

     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 } 
    View Code
  • 相关阅读:
    完全背包笔记
    渗透测试之信息收集常用网站
    结对项目-四则运算"软件"之升级版
    第三次作业:个人项目-小学四则运算“软件”之初版
    分布式版本控制系统Git的安装与使用
    第一次作业:准备
    爬虫综合大作业
    爬取全部校园新闻
    理解爬虫原理
    中文词频统计与词云生成
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/16343391.html
Copyright © 2020-2023  润新知