2017湖南多校第十三场-COJ1963-Feed the rabbit

来源:互联网 发布:怎样成为淘宝客 编辑:程序博客网 时间:2024/04/29 04:27

Feed the rabbit

Description
There are n holes in a line,the distance between the hole labeled i and i+1 is di。There are also m rabbits, the rabbit labeled i comes to hole ki in time ti. Now you have p people,you can arrange them start at any time(even before time point 0) from the first hole, their speed is 1. They head to hole n without stopping and feed the rabbit on their way without any cost of time. Now you must make every rabbit be fed just one time. You need to minimize the sum of time between arriving and fed for all rabbits.

Input
The first line includes 3 int numbers n,m,p。 The next line includes n-1 numbers,d1,d2,…dn-1。 Next m lines, every line includes 2 numbers, hi and ti, the i th line means that the i th rabbit will arriving at hole hi in time ti.

Output
One number, the minimized sum of waiting time of all rabbits.

Sample Input
4 6 2
1 3 5
1 0
2 1
4 9
1 10
2 10
3 12
Sample Output
3
Hint
30% n,m<=300 100% n,m<=10^5,1<=p<=100,1<=di<=10000,1<=hi<=n,0<=ti<=1090<=ti<=109
Source
2017湖南多校第十三场

Author
alpc

题目大意:有n个洞m只兔子,每只兔子会在ti时间于hi洞冒头(处于等待状态),有p个人,每个人都可以在任意时间内以1的速度走向第n洞并喂食沿途的兔子,求兔子最少的总等待时间。
解题思路:
这里写图片描述
如图所示,纵轴代表洞的位置,横轴代表时间,人为斜率为1的直线,将兔子映射到横轴,那么总的等待时间就是所有兔子点距离最右最近的人与横轴的交点的距离和,如图为1+2=3(即为样例1)。
设兔子点为a1,a2,,am,则问题就是如何将其分为p段(左开右闭),假设其中一段为ak,ak+1,,aj(a_k处已有直线经过),那么该段的等待时间就是ajak+1+ajak+2++ajaj=(jk)aj(ak+1+ak+2++aj)=(jk)aj(sum[j]sum[k])
dp[i][j]为将第i个直线放在第j个兔子点,所以状态转移方程就是:
dp[i][j]=min(dp[i1][k]+(jk)aj(sum[j]sum[k]))
可以推得:
如果kll<k)优,那么
dp[i1][k]+sum[k](dp[i1][l]+sum[l])kl<a[j]
这里写图片描述
如图所示g[j,k]>g[i,j]
那么如果g[i,j]<a[i]j
如果g[i,j]>=a[i],则g[j,k]>a[i],则j不比k
那么j没有存在的意义。
(斜率优化需满足横坐标递增用单调队列,如果不递增cdq分治,a[j]递增单调队列,不递增二分。)
(一般小于号维护下凸包,大于号维护上凸包)
用单调队列维护即可。
那么下凸包的点就是能够转移到最优解的点,那么是哪个呢,
对于当前决策i来说,就是要找到下凸包上斜率最接近且小于a[i]的那条线段的上端的那个点进行转移,因为下凸包斜率是递增的,很好想到二分,一个更好的选择是,因为ai也是递增的,所以如果当前从j转移过来,那么以后的最优情况也只能从j后面的点转移过来,所以用单调队列维护最优的转移点即可。

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<queue>using namespace std;typedef long long LL;const int MAXN=1e5+5;LL a[MAXN],dist[MAXN];LL rabbit[MAXN];LL dp[105][MAXN];LL q[MAXN];LL sum[MAXN];int cur,pre;//l->kLL dy(int k,int l){    return dp[pre][k]+sum[k]-(dp[pre][l]+sum[l]);}LL dx(int k,int l){    return k-l;}//k->jLL DP(int k,int j){    return dp[pre][k]+(j-k)*rabbit[j]-(sum[j]-sum[k]);}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    ios::sync_with_stdio(false);    int n,m,p;    while(cin>>n>>m>>p)    {        dist[1]=0;        for(int i=2;i<=n;++i)        {            cin>>a[i];            dist[i]=dist[i-1]+a[i];        }//        for(int i=1;i<=n;i++)//            cout<<dist[i]<<" ";//        cout<<endl;        int t1,t2;        for(int i=1;i<=m;i++)        {            cin>>t1>>t2;            rabbit[i]=t2-dist[t1];        }        sort(rabbit+1,rabbit+m+1);//        for(int i=1;i<=m;i++)//            cout<<rabbit[i]<<" ";//        cout<<endl;        sum[1]=0;        for(int i=2;i<=m;i++)        {            rabbit[i]-=rabbit[1];            sum[i]=sum[i-1]+rabbit[i];        }        rabbit[1]=0;//        for(int i=1;i<=m;i++)//            cout<<sum[i]<<" ";//        cout<<endl;        memset(dp,0x3f,sizeof(dp));        dp[0][0]=0;        int head,tail;        for(int i=1;i<=p;++i)        {            cur=i;pre=i-1;            head=0;tail=0;            q[0]=0;            for(int j=1;j<=m;++j)            {                while(head<tail&&dy(q[head+1],q[head])<=rabbit[j]*dx(q[head+1],q[head]))                    head++;                dp[cur][j]=DP(q[head],j);                while(head<tail&&dy(q[tail],q[tail-1])*dx(j,q[tail])>=dy(j,q[tail])*dx(q[tail],q[tail-1]))                    tail--;                q[++tail]=j;            }        }        cout<<dp[p][m]<<endl;    }    return 0;}
原创粉丝点击