专栏文章
题解:P8179 「EZEC-11」Tyres
P8179题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @min94ls4
- 此快照首次捕获于
- 2025/12/01 22:35 3 个月前
- 此快照最后确认于
- 2025/12/01 22:35 3 个月前
很有意思的题。
先考虑 怎么做,此时对于每个轮胎,其消耗代价是随跑的圈数单调上升的,因此可以直接贪心。将每个轮胎与其要跑的圈数放进堆里维护即可。可以做到 。
再考虑 和 同阶怎么做,令 代表考虑到前 个轮胎、目前已经跑了 圈的最小代价。转移就是一个朴素的背包:
其中 代表第 个轮胎一共跑了 圈的代价。这样直接 dp 就是 的了,如果注意到转移具有决策单调性的话,也可以二分决策点,做到 。
现在我们考虑正解。由于 ,因此对于每个轮胎,其消耗代价关于跑的圈数的函数并不是呈单调的,而是在 时出现了 的浮点。为了使这个函数单调,我们考虑根号分治,找到后面第一个代价超过浮点代价的位置 ,那么对于 的部分仍满足单调性,我们可以直接二分;对于 的部分不满足单调行,我们用 dp,限制下不能取超过 个。最后将 dp 结果与贪心结果合并取 即可。
注意到当 取 时,这一性质恰好满足!复杂度降为 ,可以通过。
CPP#include<bits/stdc++.h>
using namespace std;
const int N=505;
const int M=2e5+5;
#define int long long
int n,m,t,B;
int a[N],b[N];
long long f[N][N*25],g[M],s[M],ans=4e18;
long long calc(int i,int j){
return a[i]*j+b[i]*s[j-1];
}
struct node{
int i,j;
long long val;
bool operator <(const node &b)const{
return val>b.val;
}
};
priority_queue<node> q;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
for(int i=1;i<M;i++){
s[i]=s[i-1]+i*i;
}
cin>>n>>m>>t;
B=ceil(sqrt(t));
for(int i=1;i<=n;i++){
cin>>a[i]>>b[i];
}
for(int i=0;i<N;i++){
for(int j=0;j<N*25;j++){
f[i][j]=4e18;
}
}
f[0][0]=0;
for(int i=1;i<=n;i++){
for(int j=0;j<=min(m,B*i);j++){
for(int k=max(0ll,j-B);k<=j;k++){
f[i][j]=min(f[i][j],f[i-1][k]+(k!=j&&k!=0)*t+calc(i,j-k));
}
}
}
for(int i=1;i<=n;i++){
q.push(node{i,B+1,a[i]+1ll*b[i]*B*B});
}
for(int i=1;i<=m;i++){
node u=q.top();
q.pop();
g[i]=g[i-1]+u.val;
u.j++,u.val=a[u.i]+1ll*b[u.i]*(u.j-1)*(u.j-1);
q.push(u);
}
for(int i=0;i<=min(m,B*n);i++){
ans=min(ans,f[n][i]+g[m-i]);
}
cout<<ans;
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...