题意:
n
个老鼠,
列出dp方程:
发现这个方程在每一层中都是单调的,可以类似斜率优化维护。
#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;
}