CF311B Cats Transport

传送门


思路:

开始想没什么思路,想到的是贪心,就是能一起走的肯定要尽量一起走

所以我就将猫玩耍的时间 ti 减去路程的长度 k=2idk ,令结果为 a,这样当他们的 a 值相同时,就表示可以一起走

然后我们会发现,对于某一些猫,如果他们要一起走,那么等待的时间就是 Maxai ,这里 Max 为这群猫 ai 的最大值

这样我们就将问题转化成将 ai 排序,然后将他们分成 p 段,设每段范围为 [lk,rk],求 k=1pi=lkrkMaxka[i] 的最小值

状态转移方程为:

dp[i][k]=dp[j][k1]+(ij)×ai(sumisumj)

其中 sumi=k=1iak

这样我们就可以用斜率优化 O(np) 解决


代码:

#include<iostream> #include<fstream> #include<algorithm> #include<cmath> #include<cstdlib> #include<cstring> #include<queue> #include<map> #include<set> #include<bitset> #define LL long long inline int reads() { int sign = 1, re = 0; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') sign = -1; c = getchar();} while('0' <= c && c <= '9'){re = re * 10 + (c - '0'); c = getchar();} return sign * re; } int n, m, p; int q[100005][105], l[105], r[105]; int d[100005]; LL dp[100005][105], a[100005], sum[100005]; inline bool check(int ty, int j, double k_i) { double k_j = 1.0 * (dp[q[j][ty]][ty] + sum[q[j][ty]] - dp[q[j - 1][ty]][ty] - sum[q[j - 1][ty]]) / (q[j][ty] - q[j - 1][ty]); return k_i >= k_j; } inline bool cmp(int ty, int num) { double k_i = 1.0 * (dp[num][ty] + sum[num] - dp[q[r[ty]][ty]][ty] - sum[q[r[ty]][ty]]) / (num - q[r[ty]][ty]); double k_j = 1.0 * (dp[q[r[ty]][ty]][ty] + sum[q[r[ty]][ty]] - dp[q[r[ty] - 1][ty]][ty] - sum[q[r[ty] - 1][ty]]) / (q[r[ty]][ty] - q[r[ty] - 1][ty]); return k_i <= k_j; } signed main() { #ifndef ONLINE_JUDGE freopen("test.in", "r", stdin); freopen("test.out", "w", stdout); #endif n = reads(), m = reads(), p = reads(); for(int i = 2; i <= n; i++) d[i] = d[i - 1] + reads(); for(int i = 1; i <= m; i++) { int h = reads(), t = reads(); a[i] = t - d[h]; } std::sort(a + 1, a + 1 + m); for(int i = 1; i <= m; i++) sum[i] = sum[i - 1] + a[i]; q[l[0] = r[0] = 1][0] = 0; for(int i = 1; i <= m; i++) { for(int k = 0; k <= std::min(i - 1, p); k++) { for(int j = l[k]; j <= r[k]; j++) { bool L = j == l[k] ? true : check(k, j, a[i]), R = j == r[k] ? false : check(k, j + 1, a[i]); if(L && !R) { dp[i][k + 1] = dp[q[j][k]][k] + sum[q[j][k]] - q[j][k] * a[i] + a[i] * i - sum[i]; l[k] = j; break; } } while(r[k + 1] > l[k + 1] && cmp(k + 1, i)) r[k + 1]--; q[++r[k + 1]][k + 1] = i; } } printf("%lld", dp[m][p]); return 0; }

__EOF__

本文作者zuytong
本文链接https://www.cnblogs.com/zuytong/p/16006024.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zuytong  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示