转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
最近的比赛打得太捉鸡了,哎。
A:线性扫一遍
B:最讨厌这种题了,喵呜,果然也写挂了。
把“::”展开成若干个‘:’,使得串中刚好7个‘:’,然后再把这8个子串分开。
C:先把中间一样的去重掉。若还剩下m个数,表示如果不去掉某个数的话, 需要转换m-1次。
那么考虑某个数i,先记录一下他自己的个数b[i],如果把数字i去掉,显然会减少b[i]次转换
那么再考虑去掉某个数,两边的数刚好一样,则也不需要转换,再扫描一遍,如果两边的数一样c[i]++
int a[N],b[N],c[N];
int main()
{
int n,k;
cin>>n>>k;
for(int i=0;i<n;i++) cin>>a[i];
n=unique(a,a+n)-a;
for(int i=0;i<n;i++) b[a[i]]++;
for(int i=1;i<n-1;i++) if(a[i-1]==a[i+1]) c[a[i]]++;
int ans,mmin=inf;
for(int i=1;i<=k;i++)
{
int tmp=n-b[i]-1-c[i];
if(tmp<mmin) mmin=tmp,ans=i;
}
cout<<ans<<endl;
return 0;
}
D:纠结题意了半天,其实还是对的。
有个特点,就是起点是固定的,终点不是固定的。
枚举B,那么成了找一个A,使得|OA|+|AB|最短。显然直线最短,那么将A排序,二分求出最靠近直线的那一两个点。计算一下就可以了。
也可以三分,对于某个B,A按Y排序,显然先递减再递增。
vector<pair<double,int> >A;
int n,m,a,b;
double B[N],l[N];
int main()
{
cin>>n>>m>>a>>b;
for(int i=1; i<=n; i++)
{
double y;
cin>>y;
A.pb(mp(y,i));
}
sort(A.begin(),A.end());
// for(int i=0;i<n;i++) cout<<A[i].first<<endl;
for(int i=1; i<=m; i++) cin>>B[i];
for(int i=1; i<=m; i++) cin>>l[i];
double mmin=inf;
int ansa,ansb;
for(int i=1; i<=m; i++)
{
double y0=B[i]*1.0/b*a;
int low=0,high=n-1,mid,idx=n-1;
while(low<=high)
{
mid=(low+high)/2;
if(A[mid].first>y0){idx=mid;high=mid-1;}
else low=mid+1;
}
double tmp=l[i]+sqrt(sqr(a)+sqr(A[idx].first)+0.0)+sqrt(sqr(b-a)+sqr(B[i]-A[idx].first));
if(tmp<mmin)
{
mmin=tmp;
ansa=A[idx].second;
ansb=i;
}
if(idx>0)
{
idx--;
tmp=l[i]+sqrt(sqr(a)+sqr(A[idx].first)+0.0)+sqrt(sqr(b-a)+sqr(B[i]-A[idx].first));
if(tmp<mmin)
{
mmin=tmp;
ansa=A[idx].second;
ansb=i;
}
}
}
cout<<ansa<<" "<<ansb<<endl;
return 0;
}
E:直接模拟,记录已经拓展过的,能到达的最左最右位置。
其实比赛的时候想多了,复杂度也只是n*m
int n,m;
char str[105][10005];
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++) cin>>str[i];
int des=0; //方向
int pos=0; //当前位置
int row=0; //当前行
int l=0; //当前能向左延伸最远的
int r=0; //向右延伸最远的
LL ans=0;
int cnt=0; //记录两边是否为'#'或者边界
while(row<n-1)
{
//往下掉
if(str[row+1][pos]=='.')
{
ans++;
l=r=pos;
row++;
continue;
}
bool flag=false; //有没有遇见‘#’
//向右
if(des==0)
{
ans+=r-pos; //先走到能走的最右边
pos=r;
while(str[row+1][pos]!='.')
{
if(pos+1<m&&str[row][pos+1]=='.') //下一个是空地,直接走
{
r=pos+1;
ans++;
pos++;
}
else if(pos+1<m&&str[row][pos+1]=='+') //下一个是墙
{
str[row][pos+1]='.'; //破坏
des^=1; //反向
ans++;
break;
}
else
{
ans++;
flag=true;
des^=1;
break;
}
}
}
else
{
ans+=pos-l;
pos=l;
while(str[row+1][pos]!='.')
{
if(pos&&str[row][pos-1]=='.') //下一个是空地,直接走
{
l=pos-1;
ans++;
pos--;
}
else if(pos&&str[row][pos-1]=='+') //下一个是墙
{
str[row][pos-1]='.'; //破坏
des^=1; //反向
ans++;
break;
}
else
{
ans++;
flag=true;
des^=1;
break;
}
}
}
if(!flag) cnt=0;
else cnt++;
if(cnt>1) break; //两边都是'#'或者边界
}
if(row<n-1) puts("Never");
else printf("%I64d\n",ans);
return 0;
}