题解:P14460 【MX-S10-T1】『FeOI-4』寻雾启示
赛时做法。
首先考虑怎么做到
考虑 dp,设
转移只需要考虑搭最后一次羊毛之前已经搭了多少羊毛。
解释一下实际意义。
首先你需要保证在出发之前一共能换出来
到位置
考虑优化,先把式子化开。
通过观察这个式子我们可以如果
接下来考虑
发现内层的 max 十分的恶心,所以我们通过分讨拆掉这个 max。显然
// Problem: P14460 【MX-S10-T1】『FeOI-4』寻雾启示
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P14460
// Memory Limit: 512 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define itn int
#define retunr return
bool startmb;
constexpr int N=1e5+5;
int _,n,k,x,y;
int dp[N];
multiset<int> s;
bool endmb;
main()
{
cerr<<((&startmb-&endmb)/1024.0/1024)<<endl;
cin.tie(0)->sync_with_stdio(false);
cin>>_;
while(_--)
{
cin>>n>>k>>x>>y;
if(y-x>=0)
{
for(int i=1;i<=n;i++) cout<<i*k+x*i<<' ';
cout<<'\n';
}
else
{
s.insert(0);
for(int i=1,p=0;i<=n;i++)
{
while(p<i&&dp[p]<=i*k) s.extract(dp[p]+(y-x)*p),p++;//维护p的位置
dp[i]=i*k+(y-x)*(p-1);
if(s.size()) dp[i]=min(dp[i],*s.begin());//p后的答案
dp[i]+=(x-y)*i+y*i*2;
s.insert(dp[i]+(y-x)*i);
}
for(int i=1;i<=n;i++) cout<<dp[i]-y*i<<' ';
cout<<endl;
}
s.clear();
}
return 0;
}