CROC-MBTU 2012, Final Round (Online version, Div. 2)

来源:互联网 发布:南风知我意妈妈网 编辑:程序博客网 时间:2024/06/05 06:07

转载请注明出处,谢谢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;}



原创粉丝点击