题解 P8179
前言
EZEC R11 Problem C。
Div.1 预期通过
Div.2 预期通过
本来是想用这个题让大家笑一笑然后去轻松地开始这场比赛,结果似乎没有人笑……
关注嘉然,顿顿解馋!
Hint
每套轮胎一定只会使用一个连续的区间。
不然把这两段放一起能省一次换胎的时间。
Solution 1
我会模拟!
第
可以通过 Subtask
Solution 2
我会贪心!
如果
每套轮胎的单圈时间随着圈数上升,也就是一个单调的函数。
于是我们需要归并这
使用一个堆即可,时间复杂度
可以通过 Subtask
对于 Subtask
Solution 3
我会暴力 dp!
考虑枚举第
可以通过 Subtask
Solution 4
我会决策单调性优化!
直接优化前面的背包问题,时间复杂度可以降低到
还是只能通过 Subtask
这里忘记给一档分了,但是如果你在
这种做法是可以卡的,直接将卡堆贪心的测试点中放几个
不过这样是不是也避免了一些人去写
Solution 5
我会找性质!
不妨把换胎时间加到第一圈的时间上,这样就不存在“换胎”这个操作了。
注意到我们不能使用堆贪心是因为价格不单调,考虑强行将价格变为单调。
我们考虑记
于是我们对于每套轮胎的前
如果使用 Solution
如果使用 Solution
两者都可以通过。
Code
//And in that light,I find deliverance.
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
const int B=25;
int f[503][33],g[13003],h[200003],a[503],b[503],c[503];
struct cmp
{
bool operator()(const int&x,const int&y)
{
return (a[x]+b[x]*c[x]*c[x]>a[y]+b[y]*c[y]*c[y])||
(a[x]+b[x]*c[x]*c[x]==a[y]+b[y]*c[y]*c[y]&&x>y);
}
};
priority_queue<int,vector<int>,cmp> q;
signed main()
{
int n=read(),m=read(),d=read(),s=0;
for(int i=1; i<=n; ++i)
{
a[i]=read(),b[i]=read(),c[i]=25,q.push(i);
f[i][1]=a[i]+d;
for(int j=2; j<=B; ++j) f[i][j]=f[i][j-1]+a[i]+b[i]*(j-1)*(j-1);
}
memset(g,0x3f,sizeof(g)),g[0]=0;
for(int i=1; i<=n; ++i)
{
s=min(m,s+B);
for(int j=s; j>=0; --j)
for(int k=0; k<=B&&k<=j; ++k)
g[j]=min(g[j],g[j-k]+f[i][k]);
}
for(int i=1; i<=m; ++i)
{
int x=q.top();
q.pop(),h[i]=h[i-1]+a[x]+b[x]*c[x]*c[x],
++c[x],q.push(x);
}
int ans=0x3f3f3f3f3f3f3f3f;
for(int i=0; i<=s&&i<=m; ++i) ans=min(ans,g[i]+h[m-i]);
printf("%lld\n",ans-d);
return 0;
}