【Codeforces797F】Mice and Holes

题意:
n 个老鼠,m个洞,告诉你他们的一维坐标和 m 个洞的容量限制,问最小总距离。

列出dp方程:
dp[i][j]ij
发现这个方程在每一层中都是单调的,可以类似斜率优化维护。

#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
#define N 5009
#define inf 0x3f3f3f3f3f3f3f3fll
using namespace std;
int n,m,pos[N],S,q[N];
ll dp[N][N],sum[N];
struct node
{
    int pos,num;
    bool operator <(const node &rhs) const
    {
        return pos<rhs.pos;
    }
}a[N];
int read()
{
    int x=1;
    char ch;
    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
    int s=ch-'0';
    while (ch=gc,ch>='0'&&ch<='9') s=s*10ll+ch-'0';
    return s*x;
}
int main()
{
    n=read(),m=read();
    for (int i=1;i<=n;i++)
        pos[i]=read();
    sort(pos+1,pos+n+1);
    for (int i=1;i<=m;i++)
        a[i].pos=read(),a[i].num=read(),S+=a[i].num;
    sort(a+1,a+m+1);
    if (S<n)
    {
        puts("-1");
        return 0;
    }
    for (int i=1;i<=n;i++) dp[0][i]=inf;
    for (int i=1;i<=m;i++)
    {
        for (int j=1;j<=n;j++)
            sum[j]=sum[j-1]+abs(pos[j]-a[i].pos);
        int head=1,tail=0;
        for (int j=0;j<=n;j++)
        {
            while (head<=tail&&q[head]<j-a[i].num) head++;
            while (head<=tail&&dp[i-1][j]-sum[j]<=dp[i-1][q[tail]]-sum[q[tail]])
                tail--;//单调队列,数值逐渐增大 
            q[++tail]=j;
            dp[i][j]=dp[i-1][q[head]]-sum[q[head]]+sum[j];
        }
    }
    printf("%lld\n",dp[m][n]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值