有点懒,没补完,有时间再搞
D.Beer Flood
E.Beer Game
F. Beer Marathon
题意:
在一条直线上有 N 个啤酒摊,这些啤酒摊的位置在直线上随机摆放,题目要求是任何两个 连续啤酒摊位之间的距离应完全相同,并等于指定的特定值 K。问每个啤酒摊最少移动多少米 可以使他们之间的距离是 K 值(尽量减少所有啤酒摊位移动的总米数
思路:
题目的最优解会对应一个起点,则函数为单峰函数,因此可以三分。
因为n<=1e6,k<=1e6,所以三分范围为[-1e12,1e12]
循环 100 次为 1e8 时间复杂度,3 的 100 次方的精准度。
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=1e6+6;
int x[maxm];
int n,k;
int check(int st){
int ans=0;
for(int i=1;i<=n;i++){
ans+=abs(x[i]-st);
st+=k;
}
return ans;
}
signed main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
scanf("%lld",&x[i]);
}
sort(x+1,x+1+n);
int l=-1e12,r=1e12;
int ans=1e18;
for(int i=1;i<=100;i++){
int mid=(l+r)/2;
int midd=(mid+r)/2;
int a=check(mid);
int b=check(midd);
if(a>b){
l=mid;
}else{
r=midd;
}
ans=min(ans,min(a,b));
}
cout<<ans<<endl;
return 0;
}
I.Sixpack
J.Beer Vision
题意:
给出n个点(x,y),这n个点是其中一些点按照一个向量<X,Y>平移之后得到的新点与原来点的并集。
问这样的向量可能有多少个。
思路:
题意可转化为对于所有的集合中的点,满足+x,+y 或-x,-y 至少有一个点也在集合中。问可以选出多少个这样不同的 x 和 y。对每对点做差,满足要求的 x,y 一定在差值中至少出现了 n/2(上取整)次。这样的 x,y 显然最多有 n 个。枚举判断是否合法即可,复杂度 O(n^2)。
code:
#include<bits/stdc++.h>
using namespace std;
const int maxm=1e3+5;
int x[maxm],y[maxm];
map<pair<int,int>,int>mark;
map<pair<int,int>,int>xy;
signed main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i];
mark[{x[i],y[i]}]=1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)continue;
int xx=x[i]-x[j];
int yy=y[i]-y[j];
xy[{xx,yy}]++;
}
}
int ans=0;
for(auto i:xy){
if(i.second>=(n+1)/2){
int ok=1;
int xx=i.first.first;
int yy=i.first.second;
for(int i=1;i<=n;i++){
if(!mark[{x[i]-xx,y[i]-yy}]&&!mark[{x[i]+xx,y[i]+yy}]){
ok=0;
break;
}
}
if(ok)ans++;
}
}
cout<<ans<<endl;
return 0;
}