题解:B4281 [蓝桥杯青少年组国赛 2023] 月球疏散行动

· · 题解

题目传送门

思路

Code

#include<bits/stdc++.h>
#define endl "\n"
#define f(i,j,k) for(int i=j;i<=k;i++)
#define F(i,j,k) for(int i=j;i>=k;i--)
using namespace std;
const int maxn=4e6+10;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
inline void write(int x){
    if(x<0) {x=~(x-1); putchar('-');}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int n=read(),m=read(),tim[maxn],dp[maxn],ans,s[maxn],que[maxn],L=1,R,u,maxx;
inline double slop(int k,int j){
    int up=dp[j]+s[j]-dp[k]-s[k];
    if(tim[j]==tim[k]) return (double)up/1e-9;
    else return (double)(up/(tim[j]-tim[k]));
}
inline void work(){ 
    f(i,1,n) u=read(),tim[u]++,s[u]+=u,maxx=max(maxx,u);
    maxx+=m-1; f(i,1,maxx) tim[i]+=tim[i-1],s[i]+=s[i-1];
    f(i,1,maxx){
        if(i>=m){
            while(L<R&&slop(que[R-1],que[R])>=slop(que[R],i-m)) R--;
            que[++R]=i-m;
        }
        while(L<R&&slop(que[L],que[L+1])<=i) L++;
        dp[i]=tim[i]*i-s[i];
        if(L<=R) dp[i]=min(dp[i],dp[que[L]]+(tim[i]-tim[que[L]])*i-s[i]+s[que[L]]);
    }
    ans=dp[maxx-m+1]; f(i,maxx-m+1,maxx) ans=min(ans,dp[i]);
    write(ans);
}
signed main(){work();return !!!!!("YZren");}