好题推荐-剑指S10
题面
样例输入
2 1 3 1000 1000
0 0
1 1
1
2000
2215
4396
样例输出
0
2
-1
题解
那我问你,Xiaohu是什么生物?
思路
题目要求一个最小的非负整数 rrr,容易想到二分。可以二分答案 rrr,考虑 checkcheckcheck :可以先预处理出来 dpijdp_{i j}dpij表示点iii到点jjj的欧几里得距离,对每个dpidp_{i}dpi的第二维从小到大排序。设当前二分的答案为midmidmid,对于点aia_{i}ai,显然可以二分出第一个dpbires≤middp_{b_{i} res}≤middpbires≤mid,可以求出总伤害。综合复杂度:O(kmlog2dlog2n+nmlog2n)O(km\log_{2}{d} \log_{2}{n}+nm\log_{2}{n})O(kmlog2dlog2n+nmlog2n)。
赛时代码
#include<bits/stdc++.h>
using namespace std;
int n,m,k,e,q;
struct js
{int x,y;
}a[1005];
int b[1005];
vector<long long> dp[1005];
long long qiu(js a,js b)
{long double t=sqrt(1ll*abs(a.x-b.x)*abs(a.x-b.x)+1ll*abs(a.y-b.y)*abs(a.y-b.y));if(t!=(long double)((long long) (t))) return (long long )(t)+1;//笨拙的向上取整,不要学!else return t;
}
bool check(int x,int cha)
{long long sum=0;for(int i=1;i<=m;i++){int l=0,r=dp[b[i]].size()-1,res=0;while(l<=r){int mid=(l+r)>>1;if(dp[b[i]][mid]<=x){res=mid,l=mid+1;}else r=mid-1;}sum+=1ll*(res+1)*q+e;}return sum>=cha;
}
int main()
{freopen("wait4s10.in","r",stdin);freopen("wait4s10.out","w",stdout);cin>>n>>m>>k>>e>>q;for(int i=1;i<=n;i++){scanf("%d%d",&a[i].x,&a[i].y);}for(int i=1;i<=m;i++){scanf("%d",&b[i]);if(dp[b[i]].size()==0){for(int j=1;j<=n;j++){dp[b[i]].push_back(qiu(a[b[i]],a[j]));}sort(dp[b[i]].begin(),dp[b[i]].end());}}while(k--){int d;scanf("%d",&d);long long l=0,r=3e9,ans=3e9;while(l<=r){long long mid=(l+r)>>1;if(check(mid,d)){ans=mid,r=mid-1;}else l=mid+1;}if(ans==3e9)cout<<-1<<"\n";else cout<<ans<<"\n";}return 0;
}