2018-3-23模拟考试 青蛙

Posted on 2018-03-29 23:10  SirKnight  阅读(129)  评论(0)    收藏  举报

二分出能免费跳过去的青蛙的个数,检查时青蛙就依次跳到能跳的石头上,剩下的取代价最小的一次跳过去。

#include <stdio.h>
#include <algorithm>
using namespace std;

#define ll long long int

const int maxn=100001;
ll c[maxn],a[maxn];
ll t,n,m,k,d;

bool check(ll x)
{
	ll i;
	for(i=1;i<=x;i++)
	{
		if(a[i]-1>d)
			return 0;
	}
	for(i=x+1;i<=k;i++)
	{
		if(a[i]-a[i-x]>d)
			return 0;
	}
	for(i=k-x+1;i<=k;i++)
	{
		if(n-a[i]>d)
			return 0;
	}
	return 1; 
}

int main()
{
	scanf("%lld",&t);
	while(t--)
	{
		scanf("%lld%lld%lld%lld",&n,&m,&k,&d);
		ll i;
		for(i=1;i<=m;i++)
			scanf("%lld",&c[i]);
		sort(c+1,c+m+1);
		for(i=1;i<=k;i++)
			scanf("%lld",&a[i]);
		sort(a+1,a+k+1);
		ll l=0,r=m,sum=0;
		while(l<=r)
		{
			ll mid=(l+r)/2;
			if(check(mid))
			{
				sum=mid;
				l=mid+1;
			}
			else
				r=mid-1;
		}
		ll ans=0;
		if(sum==0)//必须有一只青蛙把所有石头都跳到 
		{
			if(a[1]-1>d)
				ans+=c[1];
			for(i=2;i<=k;i++)
			{
				if(a[i]-a[i-1]>d)
					ans+=c[1];
			}
			if(n-a[k]>d)
				ans+=c[1];
			for(i=2;i<=m;i++)
				ans+=c[i];
			printf("%lld\n",ans);
			continue;
		}
		for(i=1;i<=m-sum;i++)
			ans+=c[i];
		printf("%lld\n",ans); 
	}
	return 0;
}