1 条题解
-
0
自动搬运
来自洛谷,原作者为

lytqwq
..搬运于
2025-08-24 21:41:08,当前版本为作者最后更新于2020-11-19 16:50:16,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
因为很小,我们把每单位泥土分开看。
对于每单位泥土在第个位置上,设处理该单位泥土花费费用:
-
如果是少了泥土,可以花费费用来解决,所以,还可以向前面要泥土,要泥土一定向之前多泥土的地方要,要花费费用,但之前的泥土我们已经考虑了它的贡献了,所以之前的泥土的贡献就要再减去(即之前的那个泥土多了,但是不需要处理了,后面少了的那个泥土直接要过来了),总的费用为,所以
-
如果是多了泥土,可以花费费用来解决,所以。还可以往前面送泥土,送泥土一点向之前少泥土的地方送。同理,总的费用为,所以
这样可以直接计算了,可以解决此题的弱化版:https://www.luogu.com.cn/problem/P3049
但是对于此题,我们需要更快的方法:
拆开的计算:
所以,的计算和前面的有关的只有,要让当前的最小,我们需要让最小。
为什么我们需要让最小呢?为什么不把这个留给后面的呢?
前面的肯定是向后找最近的最好啊,越往后拖,越大,就有可能被决定,还有可能出现距离更近的来更新。
开两个小根堆,一个存本来少了泥土的单位泥土的,可以用来更新现在多了泥土的地方。
另一个存本来多了泥土的单位泥土的,可以用来更新现在少了泥土的地方。
得到处理当前泥土的费用后把存进堆里,供后面的答案更新。
可以理解为后悔的贪心,把前面的费用给减去。
时间复杂度:
AC情况:https://www.luogu.com.cn/record/42168237
代码如下:
#include<bits/stdc++.h> using namespace std; const long long int N=100001; long long int n,a[N],b[N],x,y,z; long long int V[N]; long long int ans; priority_queue<long long int,vector<long long int>,greater<long long int> > ovo,ovo2; int main(){ scanf("%lld%lld%lld%lld",&n,&x,&y,&z); for(long long int i=1;i<=n;i++){ scanf("%lld%lld",&a[i],&b[i]); for(long long int o=1;o<=a[i]-b[i];o++){ V[i]=y; if(!ovo.empty()){ V[i]=min(V[i],i*z+ovo.top()); ovo.pop(); } ovo2.push(-V[i]-i*z); ans+=V[i]; } for(long long int o=1;o<=b[i]-a[i];o++){ V[i]=x; if(!ovo2.empty()){ V[i]=min(V[i],i*z+ovo2.top()); ovo2.pop(); } ovo.push(-V[i]-i*z); ans+=V[i]; } } printf("%lld\n",ans); } -
- 1
信息
- ID
- 5141
- 时间
- 2000ms
- 内存
- 250MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者