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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章