题目链接:http://codeforces.com/problemset/problem/311/B
题意:有1到n共n座山。m个牛。每个牛都 在某一个山上吃草。第i个牛在时间ti时刻吃完草然后在山下等着管理员来牵走。给出相邻两座山之间的距离。已知有P个管理员。管理员从1出发依次到n将正 在等的牛牵走。注意管理员不会在山下等牛,只牵走正在等的牛。管理员的走路速度为1。假如1到2的距离为10,那么管理员2时刻从1出发,到达2的时刻为 12。合理安排每个管理员从1的出发时间使得牛的总等待时间最少?
思路:设第i个山距离第1个山的距离为 d[i],第j个牛在第i个山上,那么保存a[j]=j-d[i]。将a排序。那么问题转化为将a[1]-a[m]最多分成P组,每组的代价为这组中每个 数与最大的那个数的差的和。使得总代价最少。设s[i]=a[1]+a[2]+……a[i]。f[i][j]表示前j个分成i组的最小代价,那么显然有: f[i][j]=f[i-1][k]+(j-k)*a[j]-(s[j]-s[k])=j*a[j]+f[i-1][k]+s[k]-a[j]*k。这个 复杂度太大。我们试图化简。设两个k1,k2,满足k2>k1但是k2比k1更优,那么f[i-1] [k1]+s[k1]-a[j]*k1>=f[i-1][k2]+s[k2]-a[j]*k2。令dy(k1,k2)=(f[i-1] [k1]+s[k1])-(f[i-1][k2]+s[k2]),dx(k1,k2)=k1-k2,那么上式等价于:dy(k1,k2)>=a[j]*dx(k1,k2)。进而我们可以使用单调队列优化,复杂度为O(Pm)。
int n,m,P;
i64 f[2][N],s[N],b[N],a[N];
int Q[N],L,R,pre,cur;
i64 dy(int p,int q)
{
return (f[pre][p]+s[p])-(f[pre][q]+s[q]);
}
i64 dx(int p,int q)
{
return p-q;
}
int main()
{
RD(n,m,P);
int i,j,k,x;
for(i=2;i<=n;i++) RD(b[i]),b[i]+=b[i-1];
FOR1(i,m) RD(x),RD(a[i]),a[i]-=b[x];
sort(a+1,a+m+1);
FOR1(i,m) s[i]=s[i-1]+a[i];
if(P>=m)
{
puts("0");
return 0;
}
pre=0;cur=1;
FOR1(i,m) f[0][i]=i*a[i]-s[i];
FOR1(k,P-1)
{
L=R=0; Q[0]=0;
FOR1(i,m)
{
while(L<R&&dy(Q[R-1],Q[R])*dx(Q[R],i)>=dy(Q[R],i)*dx(Q[R-1],Q[R])) R--;
Q[++R]=i;
while(L<R&&dy(Q[L],Q[L+1])>=a[i]*dx(Q[L],Q[L+1])) L++;
j=Q[L];
f[cur][i]=f[pre][j]+(i-j)*a[i]-s[i]+s[j];
}
swap(pre,cur);
}
PR(f[pre][m]);
}