一、题目
二、解法
先考虑可能的集合点,就是所有的 到 ,我们把余数相同的归到一类,方便处理。
对于每一类余数相同的,维护一个大小为 的优先队列,因为要整体修改(移动 的倍数步),所以可以维护一个懒标记,然后就看码力了
#include <cstdio>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
#define int long long
const int M = 200005;
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,k,x,y,ans,a[M];
vector<int> v[5];
int cal(int u,int v)
{
int d=(v-u);
return (d/5)*x+(d%5)*y;
}
void work(int d)
{
priority_queue<int> q;
int j=1,s=0,la=0;
for(int i=0;i<v[d].size();i++)
{
while(j<=n && a[j]<=v[d][i])
{
int ct=cal(a[j],v[d][i]);
s+=ct;
q.push(ct-la);
if(q.size()>k)
{
s-=(q.top()+la);
q.pop();
}
j++;
}
if(q.size()>=k) ans=min(ans,s);
if(i+1<v[d].size())
{
int t=((v[d][i+1]-v[d][i])/5)*x;
la+=t;
s+=t*q.size();
}
}
}
signed main()
{
n=read();k=read();x=read();y=read();
for(int i=1;i<=n;i++)
{
a[i]=read()+1e9;
for(int j=0;j<5;j++)
v[(a[i]+j)%5].push_back(a[i]+j);
}
sort(a+1,a+1+n);
ans=1e18;
for(int i=0;i<5;i++)
{
sort(v[i].begin(),v[i].end());
work(i);
}
printf("%lld\n",ans);
}