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