

二分出能免费跳过去的青蛙的个数,检查时青蛙就依次跳到能跳的石头上,剩下的取代价最小的一次跳过去。
#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;
}
浙公网安备 33010602011771号