1. 程式人生 > 其它 >CF1557 D. Ezzat and Grid(dp+線段樹)

CF1557 D. Ezzat and Grid(dp+線段樹)

目錄

Description

\(n\)\(01\) 串, 其中有 \(m\) 個區間 \([l,r]\) 內的字元為 \(1\)

如果兩行之中有任意一個位置 \(x\), 都為 \(1\), 那麼這兩行相互連線,求刪除儘可能少的行,使得每一行都相互連線

State

\(1<=n,m<=3*10^{5}\)

\(1<=l<=r<=10^9\)

Input

3 6
1 1 1
1 7 8
2 7 7
2 15 15
3 1 1
3 15 15

Output

0

Solution

題目就是一道簡單 dp + 記錄答案

\(dp[i]=max(dp[j]+1),j∈[1,i-1]\)

如果找到了第 \(j\) 行,使得 \(dp[i]\) 最大,我們需要知道的值有 \((dp[j],j)\) 兩個;

那麼該怎樣找到這個 \(j\) 呢,如果第 \(i\) 行的任意一個區間與 \(j\) 上的區間重合就可以,而第 \(i\) 行上的區間更新上這個最大值就可以保證之後最大值的成立

\(hack:\)

線段樹的大小為區間的端點數

Code

const int N = 3e5 + 5;

    ll n, m, _;
    int i, j, k;
    vector<pii> a[N];
    struct Node
    {
        int l, r;
        pii maxx, lazy;
        #define lson id << 1
        #define rson id << 1 | 1
        void update(pii x)
        {
            lazy = max(lazy, x);
            maxx = max(maxx, x);
        }
    }t[N << 3];

void push_up(int id)
{
    t[id].maxx = max(t[lson].maxx, t[rson].maxx);
}

void push_down(int id)
{
    pii &x = t[id].lazy;
    if(x.fi){
        t[lson].update(x);
        t[rson].update(x);
        x = {0, 0};
    }
}

void build(int l, int r, int id)
{
    t[id].l = l, t[id].r = r;
    t[id].maxx = t[id].lazy = {0, 0};
    if(l == r){
        return ;
    }
    else{
        int mid = l + r >> 1;
        build(l, mid, lson);
        build(mid + 1, r, rson);
        return ;
    }
}

void update(int l, int r,int id, pii x)
{
    int L = t[id].l, R = t[id].r;
    if(L >= l && r >= R){
        return t[id].update(x);
    }
    else{
        int mid = L + R >> 1;
        push_down(id);
        if(mid >= l) update(l, r, lson, x);
        if(r >= mid + 1) update(l, r, rson, x);
        push_up(id);
    }
}

pii query(int l, int r, int id)
{
    int L = t[id].l, R = t[id].r;
    if(L >= l && r >= R){
        return t[id].maxx;
    }
    else{
        pii ans(0, 0);
        int mid = L + R >> 1;
        push_down(id);
        if(mid >= l) ans = max(ans, query(l, r, lson));
        if(r >= mid + 1) ans = max(ans, query(l, r, rson));
        push_up(id);
        return ans;
    }
}

vector<int> v;
int getid(int x)
{
    return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
}

int recreat()
{
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    for(int i = 1; i <= n; i ++){
        for(auto &it : a[i]){
            it.fi = getid(it.fi);
            it.se = getid(it.se);
        }
    }
    return v.size();
}

int pre[N], dp[N], vis[N];
void print()
{
    pii maxx(0, 0);
    for(int i = 1; i <= n; i ++){
        maxx = max(maxx, {dp[i], i});
    }
    int id = maxx.se;
    while(id != -1){
        vis[id] = 1;
        id = pre[id];
    }
    vector<int> ans;
    rep(i, 1, n){
        if(! vis[i]) ans.pb(i);
    }
    int sz = ans.size();
    pd(sz);
    rep(i, 0, sz - 1){
        printf("%d ", ans[i]);
    }
}

signed main()
{
    //IOS;
    while(~ sdd(n, m)){
        int id, l, r;
        rep(i, 1, m){
            sddd(id, l, r);
            a[id].pb(pii(l, r));
            v.pb(l), v.pb(r);
        }
        int sz = recreat();
        build(1, sz, 1);
        fill_n(pre, N, -1);
        rep(i, 1, n){
            pii ans(0, 0);
            for(auto it : a[i]){
                int l = it.fi, r = it.se;
                ans = max(ans, query(l, r, 1));
            }
            dp[i] = dp[ans.se] + 1;
            pre[i] = ans.se;
            ans = {dp[i], i};
            for(auto it : a[i]){
                int l = it.fi, r = it.se;
                update(l, r, 1, ans);
            }
        }
        print();
    }
    //PAUSE;
    return 0;
}