首页 > 其他分享 >CodeForces - 311B Cats Transport

CodeForces - 311B Cats Transport

时间:2022-11-24 15:25:14浏览次数:45  
标签:maxx int sum CodeForces 猫猫 Cats Transport dp define

题意:洛谷翻译超可爱的放一下qwq

解:先设dp[i][j]为安排前 i 个人接前 j 只猫的最小等待时间。显然要给猫排个序。猫可以等人,但人不会等猫。于是算一下每只猫需要人在什么时候出发,刚好能接到,这样就保证了人能接到连续一段猫猫。我们称这个时间为猫猫时间(dbq猫猫真的太可爱了)。如果要接[k, j]的猫,只能按照第 j 只猫的猫猫时间出发,不然接不到前面的猫,于是这一段猫猫的等待时间为(j-k+1)*h[j]-sum[k...j]。按这个推一下式子,转移即可。

顺带一提如果人类的数量大于猫猫,那可以安排每个人接一只猫,总时间为0.

代码:

#include <bits/stdc++.h>
using namespace std;
#define maxx 100005
#define maxn 25
#define maxm 205
#define ll long long
#define inf 1000000009
#define mod 2520
ll dp[105][maxx]={0};
ll sum[maxx]={0};
ll d[maxx],h[maxx],t[maxx];
int q[maxx]={0};
double cal(int m,int n,int i){
    return ((double)dp[i-1][m]-dp[i-1][n]+sum[m]-sum[n])/(m-n);
}
signed main() {
    int n,m,p;
    scanf("%d%d%d",&n,&m,&p);
    for(int i=2;i<=n;i++){
        scanf("%lld",&d[i]);
    }
    for(int i=1;i<=n;i++){
        d[i]=d[i]+d[i-1];
    }
    for(int i=1;i<=m;i++){
        scanf("%lld%lld",&h[i],&t[i]);
    }
    if(p>=m){
        printf("0\n");
        return 0;
    }
    for(int i=1;i<=m;i++){
        t[i]=t[i]-d[h[i]];
    }
    sort(t+1,t+m+1);
    for(int i=1;i<=m;i++){
        sum[i]=sum[i-1]+t[i];
    }
    dp[1][0]=0;
    for(int i=1;i<=m;i++){
        dp[1][i]=i*t[i]-sum[i];
    }
    for(int i=2;i<=p;i++){
        int head=1,tail=1;
        q[head]=0;
        for(int j=1;j<=m;j++){
            while(head<tail&&cal(q[head],q[head+1],i)<t[j]) head++;
            int k=q[head];
            dp[i][j]=dp[i-1][k]+(j-k)*t[j]-sum[j]+sum[k];
            while(head<tail&&cal(q[tail-1],q[tail],i)>=cal(q[tail],j,i)) tail--;
            q[++tail]=j;
        }
    }
    printf("%lld\n",dp[p][m]);
}
// a[i]=t[i]-h[i]
// dp[i][j] use i feeder to take the first j cats
// dp[i][j]=min(dp[i-1][k]+val(k+1,j))
// val(k+1,j)=num*a[j]-sum[k+1...j]=(j-k)*a[j]-sum[j]+sum[k]
// dp[i][j]=min(dp[i-1][k]+(j-k)*a[j]-sum[j]+sum[k])
// dp[i][j]=min(dp[i-1][k]+j*a[j]-sum[j]+sum[k]-k*a[j])
// if m is better than n
// dp[i-1][m]+sum[m]-m*a[j]<dp[i-1][n]+sum[n]-n*a[j]
// (dp[i-1][m]-dp[i-1][n]+sum[m]-sum[n])/(m-n)<a[j]
View Code

顺便发点今日份猫fei猫mi

 

标签:maxx,int,sum,CodeForces,猫猫,Cats,Transport,dp,define
From: https://www.cnblogs.com/capterlliar/p/16921940.html

相关文章

  • Codeforces Round #621 (Div. 1 + Div. 2) D
    D.CowandFields对于每个点我们可以通过两次bfs求出他离1最近的距离和离n最近的距离对于连边就是让d1[i]+d2[j]+1去更新最短路我们要让d1[i]+d2[j]+1最大我们先直......
  • Codeforces Round #771 (Div. 2) E Colorful Operations
    ColorfulOperations珂朵莉树+树状数组||线段树单独维护点当前的值\(val\)和当前颜色的值\(tag\)这样就可以分开维护颜色和点的值,把复杂的操作\(2\)变成\(O(......
  • Codeforces Round #804 (Div. 2) C D
    C1700D2300所以我并没有做水题。考虑0的位置一定不动再考虑1的位置也不动考虑2的位置不妨设0的位置为L1的位置为R那么若2的位置在L~R之间那么2就可以随便放......
  • Codeforces Round #835 (Div. 4) A-G完全题解
    比赛链接A、点击查看代码#include<bits/stdc++.h>usingnamespacestd;intmain(){intT;cin>>T;while(T--){vector<int>G;for(inti=1;......
  • Codeforces Round #831 (Div. 1 + Div. 2)
    C核心思路:这个题目其实是一个规律题,它有一个很重要的前提,那就是在分配方案最优的情况下,要不然我们直接选几个差值最大的就ok,那他这句话,其实我们结合几个样例就知道,有一个......
  • Codeforces Round #790 (Div.4) A-H2题解
    原题链接:https://codeforces.com/contest/1676A.Lucky?题意:给定长度为6由数字组成的字符串问前三个数字的和是否等后三个数字的和。题解:直接相加比较即可。#include<......
  • Codeforces Round #835 (Div.4) A-G题解
    原题链接:https://codeforces.com/contest/1744A.MediumNumber题意:给定三个数,求中间那个数(倒数第二小or倒数第二大)。题解:直接用数组存,sort一下输出中间的数即可。#in......
  • Educational Codeforces Round 36 (Rated for Div. 2) E Physical Education Lessons
    PhysicalEducationLessons珂朵莉树模板#include<iostream>#include<cstdio>#include<set>usingnamespacestd;#defineItset<ran>::iteratorstructran{......
  • Codeforces Round #449 (Div. 1) C Willem, Chtholly and Seniorious
    Willem,ChthollyandSeniorious珂朵莉树慕名而来操作\(3\)直接排序是我没想到的,因为随机数据所以才能过吧\(split\)操作中忘了开\(longlong\),\(wa3\)#include<......
  • Codeforces Global Round 23 D
    D.PathsontheTree思考问题我们发现我们路径总是可以走到底的而不会中途中断而且对于每一个分叉点也就是每个儿子至少都会有当前还剩的k/儿子数取余剩下的我们可以......