【Codeforces797F】Mice and Holes

来源:互联网 发布:安卓放弃java 编辑:程序博客网 时间:2024/05/20 18:02

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

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

#include <bits/stdc++.h>#define gc getchar()#define ll long long#define N 5009#define inf 0x3f3f3f3f3f3f3f3fllusing 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;}
原创粉丝点击