ながめも

競技プログラミングについて

Codeforces Round #658 (Div. 2) 参加記

B - Sequential Nim

最初に a_i > 1に到達した方が、常に先に山に手をつけることができる。これは、次が a_i > 1なら、その山を 1だけ残して相手に渡し、次が 1の場合は山を全て取ることで実現できる。よって、到達するまでの回数を数えればよい。注意点として、最後の山は数えない。

void solve(){
    int N;
    cin >> N;
    vector<int> a(N);
    rep(i,N)cin >> a[i];
    int cnt = 0;
    rep(i,N-1){
        if(a[i] == 1)cnt++;
        else break;
    }
    cout << ((cnt%2 == 0)? "First": "Second") << endl;
}

C - Prefix Flip

Easy Version

右から揃えていく。 iが揃っていない場合、反転させるためには、 a_0 == a_iであることが条件である。この条件を満たしていない場合は、先頭だけの処理を挟めばよい。

 \Theta(N^{2})である。

void solve(){
    int N;
    cin >> N;
    string a, b;
    cin >> a >> b;
    auto f = [&](int x){
        //cerr << x << ":" << endl << a << endl;
        rep(i,x+1){
            a[i] = char(((a[i] - '0') ^ 1) + '0');
        }
        reverse(a.begin(), a.begin()+x+1);
        //cerr << a << endl;
    };
    vector<int> ans;
    for(int i = N-1; i >= 0; i--){
        if(a[i] == b[i])continue;
        if(a[0] == a[i]){
            f(i);
            ans.push_back(i+1);
        }
        else{
            f(0);
            ans.push_back(1);
            f(i);
            ans.push_back(i+1);
        }
        //dump(a);
    }
    cout << ans.size() << " ";
    for(auto v: ans){
        cout << v << " ";
    }
    cout << endl;
}

Hard Version

右から揃えていくのは変わらないが、reverseを実装するとTLEになる。 ここで、reverseする代わりに、左右端のindex  l,rを持ち、reverseされることをswap(l,r)に言い換える。また、間が何回反転されたかも持つ。間がどこにあるかを持つ必要はない。先頭だけの処理もあるので、個別の反転回数も持って、合計何回反転されたかをもてば偶奇でわかるようになる。

 \Theta(N)

void solve(){
    int N;
    cin >> N;
    string a, b;
    cin >> a >> b;
    vector<int> x(N), y(N);
    rep(i,N){
        x[i] = a[i] - '0';
        y[i] = b[i] - '0';
    }
    int l = 0;
    int r = N-1;
    int cnt_all = 0;
    vector<int> cnt(N,0);
    vector<int> ans;
    for(int i = N-1; i >= 0; i--){
        int xr = x[r] + cnt_all + cnt[r];
        int xl = x[l] + cnt_all + cnt[l];
        xr %= 2;
        xl %= 2;
        if(xr == y[i]){
            if(l < r)r--;
            else r++;
            continue;
        }
        if(xl != xr){
            xl ^= 1;
            cnt[l]++;
            ans.push_back(1);
        }
        swap(l,r);
        ans.push_back(i+1);
        cnt_all++;
        if(l < r)r--;
        else r++;
    }
    cout << ans.size() << " ";
    for(auto v: ans){
        cout << v << " ";
    }
    cout << endl;
}