2018美团CodeM 题解
2018美团CodeM 题解
我现场打了3题,看看稳进复赛,就不打了。
T1
这题很简单,先扫一趟刷出最大值,标记最大值出现的时候,然后在扫一遍输出答案,这样效率高。
代码如下:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,k,MAXT,Now,hsh[505][505],ans[505][505],ID;
struct xcw{
int x,y,z;double t;
bool operator <(const xcw b)const{return t<b.t;}
}a[100005];
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=k;i++){
int x,y,z,h,m;double s;
scanf("%d%d%d%d:%d:%lf",&x,&y,&z,&h,&m,&s);
a[i]=(xcw){x,y,z,s+(double)h*3600+(double)m*60};
}
sort(a+1,a+1+k);
for(int i=1;i<=k;i++){
if(a[i].z==0){
if(hsh[a[i].x][a[i].y]==0) Now++;
hsh[a[i].x][a[i].y]++;
}else{
if(hsh[a[i].x][a[i].y]==1) Now--;
hsh[a[i].x][a[i].y]--;
}
if(Now>=MAXT) MAXT=Now,ID=i;
}
memset(hsh,0,sizeof(hsh));
for(int i=1;i<=ID;i++)
if(a[i].z==0) hsh[a[i].x][a[i].y]++;
else hsh[a[i].x][a[i].y]--;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) printf(j==m?"%d\n":"%d",hsh[i][j]>0);
return 0;
}
T2
这题我没打,但是我们机房XYZ dalao打掉了此题(卡在95%一个小时一直过不了,最后发现-1没判),他的想法就是DP,我没有仔细问。
T3
这题其实不难,首先我们知道l=1时最优,这个好证,那么r怎么办,其实也不难,推一下就知道了,最高位与n的最高位相同,然后在不大于n的情况下1越多越好。这个推出来了,那么就简单了。
代码如下:
#include<cstdio>
#include<cstring>
using namespace std;
int n,Ans,Len;
char ch[20005];
int main(){
#ifndef ONLINE_JUDGE
freopen("T3.in","r",stdin);
freopen("T3.out","w",stdout);
#endif
gets(ch+1);Len=strlen(ch+1);
for(int i=2;i<=Len;i++){
if(ch[i]=='1'){
bool t=1;
for(int j=i+1;j<=Len;j++) if(ch[j]=='0'){t=0;break;}
if(!t){
ch[i]='0';
for(int j=i+1;j<=Len;j++) ch[j]='1';
}
break;
}
}
for(int i=1;i<=Len;i++) Ans+=(ch[i]=='1');
for(int i=3;i<=Len;i++) Ans+=i-1;
printf("%d\n",Ans);
return 0;
}
T4
平面几何题,我们会发现这个答案是一个单峰函数,那么果断三分,但是我不会QAQ。我就讲讲我的另一个暴力的想法。
![]()
R是已知的,我们只需要枚举D,就能确定这个圆上的点,如果每次D+=1e-6的话,肯定超时,我们知道这是单峰函数,那么我们就枚举表示D每次的增量,我们想让答案越精确,那么就得越小。
答案Ans的值Just like this:
![]()
每次去求当长度等于的答案和的答案,如果当前出现这种情况,那么答案就在之间,那么就将减小,继续找。我选择每次除以1000,然后精度定在1e-9,所以这个算法的复杂度就是O(4*1000)。
我的表达不太好,所以还不懂的只能看代码了。
代码如下:
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int f[4][2]={{1,1},{-1,1},{1,-1},{-1,-1}};
double R,L,Lst,rx1,rx2,ry1,ry2,x,_x,y,_y,Ans=1e99;
double Check(double D){
double xx,yy,_xx,_yy;
xx=D,yy=sqrt(R*R-D*D);_xx=-D,_yy=-yy;
return sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy))+sqrt((_x-_xx)*(_x-_xx)+(_y-_yy)*(_y-_yy));
}
int main(){
#ifndef ONLINE_JUDGE
freopen("T4.in","r",stdin);
freopen("T4.out","w",stdout);
#endif
scanf("%lf%lf%lf%lf%lf",&R,&rx1,&ry1,&rx2,&ry2);
for(int i=0;i<4;i++){//我感觉这个函数有两个峰,因为时间关系,没有去证,直接旋转这个圆来求解。
x=rx1*f[i][0];y=ry1*f[i][1];
_x=rx2*f[i][0];_y=ry2*f[i][1];
Lst=Check(-R);L=R;
for(double D=-L+1;D<=L;D+=1){
double Now=Check(D);
if(Lst<=Now){L=D-1;break;}
Lst=Now;
}
Lst=Check(L);
for(double D=L+(1e-3);D<=L+1;D+=1e-3){
double Now=Check(D);
if(Lst<=Now){L=D-(1e-3);break;}
Lst=Now;
}
Lst=Check(L);
for(double D=L+(1e-6);D<=L+(1e-3);D+=1e-6){
double Now=Check(D);
if(Lst<=Now){L=D-(1e-6);break;}
Lst=Now;
}
Lst=Check(L);
for(double D=L+(1e-9);D<=L+(1e-6);D+=1e-9){
double Now=Check(D);
if(Lst<=Now){L=D-(1e-9);break;}
Lst=Now;
}
Ans=min(Ans,Check(L));
}
Ans=min(Ans,sqrt((rx1-rx2)*(rx1-rx2)+(ry1-ry2)*(ry1-ry2)));
printf("%.10lf",Ans);
return 0;
}
T5~T6
题目没来的及看。