CF639D Bear and Contribution

一、题目

点此看题

二、解法

先考虑可能的集合点,就是所有的 a i a_i a i + 4 a_i+4 ,我们把余数相同的归到一类,方便处理。

对于每一类余数相同的,维护一个大小为 k k 的优先队列,因为要整体修改(移动 5 5 的倍数步),所以可以维护一个懒标记,然后就看码力了

#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);
}

猜你喜欢

转载自blog.csdn.net/C202044zxy/article/details/107523481