Codeforces Round #619 (Div. 2) 题解

A. Three Strings
题意:给出三个长度相等的字符串a,b,c,对于每一位a或b中的一个和c交换,是否存在使得a,b相等的情况。
思路:直接枚举c的每一位是否和a或b相同,相同则和不相同的那个交换,没有相同的则无解

#include<bits/stdc++.h>
using namespace std;
string a,b,c;
void solve(){
    for(int i=0;i<(int)a.size();++i){
        if(a[i]==c[i]||b[i]==c[i]) continue;
        else {
            cout<<"NO\n";
            return ;
        }
    }
    cout<<"YES\n";
}
int main(){
    int T;
    cin>>T;
    while(T--){
        cin>>a>>b>>c;
        solve();
    }
    return 0;
}

B. Motarack's Birthday
题意:给出有n个数字的序列,数字是-1表示需要被替换,求找到一个k替换所有-1使得每个相邻数字之间的绝对值差最大的最小。
思路:三分枚举k,因为(x=k,y=绝对值的差)可以构成一个凹形的函数。应该也可以二分枚举绝对值,不过太难实现了。

#include<bits/stdc++.h>
using namespace std;
int a[100010],b[100010],n;
int check(long long k){
    for(int i=1;i<=n;++i){
        if(a[i]==-1) b[i]=k;
    }
    int Max=0;
    for(int i=1;i<=n-1;++i){
        Max=max(abs(b[i]-b[i+1]),Max);
    }
    return Max;
}
int main(){
    int T;
    cin>>T;
    while(T--){
        cin>>n;
        for(int i=1;i<=n;++i){
            cin>>a[i];
            b[i]=a[i];
        }
        long long l=0,r=1e9;
        int m=1e9,k;
        for(int i=1;i<=100;++i){
            long long ll=(l*2+r)/3;
            long long rr=(l+r*2)/3;
            int resl=check(ll);
            int resr=check(rr);
            if(resl>resr){
                l=ll;
                m=resr;
                k=rr;
            }
            else {
                r=rr;
                m=resl;
                k=ll;
            }
        }
        cout<<m<<" "<<k<<"\n";
    }
    return 0;
}

C. Ayoub's function
题意:用m个'1',n-m个'0'构造一个串,使得包含'1'的子串尽可能的多。例如:
"01010" 有12个子串包含'1':(1,2),(1,3),(1,4),(1,5),(2,2),(2,3),(2,4),(2,5),(3,4),(3,5),(4,4),(4,5)。
思路:容易想到让'1'的位置尽量均匀的分开答案最大,但是分开后子串的数量统计有点困难。正难则反,我们去用所有子串的数量减去全'0'串的数量得到的就是包含'1'的子串数量。(长度为n的串具有n*(n+1)/2个子串)

#include<bits/stdc++.h>
using namespace std;
int n,m;
void solve(){
    long long ans=1ll*(n+1)*n/2;
    n=n-m; //0的数量
    m=m+1;//全0串数量
    long long a=n/m,b=n%m ;//每个串最少有a个0,b个串有a+1个0
    ans=ans-a*(a+1)/2*(m-b)-(a+1)*(a+2)/2*b;
    cout<<ans<<'\n';
}
int main(){
    int T;
    cin>>T;
    while(T--){
        cin>>n>>m;
        solve();
    }
    return 0;
}

D. Time to Run
题意:在一个如图的地图中每个格子到相邻的格子都有两个方向的边,求从是否存在从(0,0)出发,且每条边只有一次的共走k的方案,如果有按[次数-移动]的格式输出,输出不能超过3000行,移动不超过4个字符。

思路:模拟题。首先找到一个可以把则(4nm−2n−2m)的方法,就是先向右走到最后一列,再向下向上向左,一直走到第一列,然后向下继续这样走,直到走完最后一行后还剩下所有行第一列的向上的边没走,那么最后还回到了(0,0)。剩下的就是做模拟了。

#include<bits/stdc++.h>
using namespace std;
struct ac{
    string s;
    int t,l;
    int id;
};
vector<ac> v;
int main(){
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    int tot=4*m*n-2*n-2*m;
    if(tot<k){
        puts("NO");
    }
    else {
        string tdur="DUL";
        for(int i=1;i<n;++i){
            if(m-1!=0){
                v.push_back((ac){"R",m-1,1,1});
                v.push_back((ac){tdur,m-1,3,2});
            }
            if(n!=1)
            v.push_back((ac){"D",1,1,3});
        }
        if(m-1!=0){
            v.push_back((ac){"R",m-1,1,4});
            v.push_back((ac){"L",m-1,1,5});
        }
        if(n!=1)
        v.push_back((ac){"U",n-1,1,6});
        tot=0;
        puts("YES");
        int res=0;
        tot=0;
        for(int i=0;i<v.size();++i){
            tot+=v[i].t*v[i].l;
            if(tot<=k){
                ++res;
            }
            else {
                tot-=v[i].t*v[i].l;
                int gap=k-tot;
                if(v[i].id==1){
                    res++;
                }
                else if(v[i].id==2){
                    if(gap/3>0){
                        res++;
                    }
                    if(gap-gap/3*3>0){
                        res++;
                    }
                    if(gap-gap/3*3>1){
                        res++;
                    }
                }
                else if(v[i].id==3){
                        res++;
                }
                else {
                        res++;
                }
                break;
            }
            if(tot==k) {
                break;
            }
        }
        cout<<res<<'\n';
        tot=0;
        for(int i=0;i<v.size();++i){
            tot+=v[i].t*v[i].l;
            if(tot<=k){
                ++res;
                cout<<v[i].t<<" "<<v[i].s<<endl;
            }
            else {
                tot-=v[i].t*v[i].l;
                int gap=k-tot;
                if(v[i].id==1){
                    res++;
                    cout<<gap<<" R\n";
                }
                else if(v[i].id==2){
                    if(gap/3>0){
                        cout<<gap/3<<" DUL\n";
                        res++;
                    }
                    if(gap-gap/3*3>0){
                        cout<<"1 D\n";
                        res++;
                    }
                    if(gap-gap/3*3>1){
                        cout<<"1 U\n";
                        res++;
                    }
                }
                else if(v[i].id==3){
                        res++;
                    cout<<"1 D\n";
                }
                else {
                    cout<<gap<<" "<<v[i].s;
                }
                break;
            }
            if(tot==k) {
                break;
            }
        }
    }
    return 0;
}
posted @ 2020-03-18 14:28  0x4f  阅读(123)  评论(0编辑  收藏  举报