G - 01Sequence Editorial by kusano


\(A_i\)\(0\) で初期化し、\(R_i\) の小さな順に条件を満たしていきます。

\(i\) 番目の条件を処理する時点で、\(L_i\) から \(R_i\) の区間に含まれる \(0\) の個数 \(n\)\(X_i\) 個未満ならば、\(X_i-n\) 個の \(0\)\(1\) に変える必要があります。このとき、\(R_i\) 以下で最大の位置を書き換えるのが最善です。

\(L_i\) から \(R_i\) の区間に含まれる \(0\) の個数は、Fenwick Treeによって \(O(\log n)\)で数えることができます。書き換える場所については、 \(R_i\) 以下の位置をスタックに入れていけば良いです。

実行時間は遅くなりますが、Segtreeを使うと考えることが減って楽かもしれません。

C++での実装例(Fenwick Treeとキュー):

#include <iostream>
#include <vector>
#include <algorithm>
#include <atcoder/fenwicktree.hpp>
using namespace std;

int main()
{
    int N, M;
    cin>>N>>M;
    vector<int> L(M), R(M), X(M);
    for (int i=0; i<M; i++)
    {
        cin>>L[i]>>R[i]>>X[i];
        L[i]--;
    }

    vector<int> I(M);
    for (int i=0; i<M; i++)
        I.push_back(i);
    sort(I.begin(), I.end(), [&](int x, int y){return R[x]<R[y];});

    vector<int> A(N);
    atcoder::fenwick_tree<int> FT(N);
    //  1を書き込める位置
    vector<int> Q;
    //  Qに未追加の最小の位置
    int q = 0;
    for (int i: I)
    {
        for (; q<R[i]; q++)
            Q.push_back(q);

        //  書き込まなければならない1の個数
        int n = X[i]-FT.sum(L[i], R[i]);
        for (int j=0; j<n; j++)
        {
            int p = Q.back();
            Q.pop_back();

            A[p] = 1;
            FT.add(p, 1);
        }
    }

    for (int i=0; i<N; i++)
        cout<<(i==0 ? "" : " ")<<A[i];
    cout<<endl;
}

C++での実装例(Segtree):

#include <iostream>
#include <vector>
#include <algorithm>
#include <atcoder/segtree.hpp>
using namespace std;

int op_add(int a, int b) {return a+b;}
int op_max(int a, int b) {return max(a, b);}
int e_0() {return 0;}
int e_m1() {return -1;}

int main()
{
    int N, M;
    cin>>N>>M;
    vector<int> L(M), R(M), X(M);
    for (int i=0; i<M; i++)
    {
        cin>>L[i]>>R[i]>>X[i];
        L[i]--;
    }

    vector<int> I(M);
    for (int i=0; i<M; i++)
        I.push_back(i);
    sort(I.begin(), I.end(), [&](int x, int y){return R[x]<R[y];});

    vector<int> A(N);
    atcoder::segtree<int, op_add, e_0> ST_sum(N);
    atcoder::segtree<int, op_max, e_m1> ST_pos(N);
    for (int i=0; i<N; i++)
        ST_pos.set(i, i);
    for (int i: I)
    {
        //  書き込まなければならない1の個数
        int n = X[i]-ST_sum.prod(L[i], R[i]);
        for (int j=0; j<n; j++)
        {
            int p = ST_pos.prod(L[i], R[i]);
            A[p] = 1;
            ST_sum.set(p, 1);
            ST_pos.set(p, -1);
        }
    }

    for (int i=0; i<N; i++)
        cout<<(i==0 ? "" : " ")<<A[i];
    cout<<endl;
}

posted:
last update: