1. 程式人生 > 其它 >Codeforces Round #737 (Div. 2) D. Ezzat and Grid

Codeforces Round #737 (Div. 2) D. Ezzat and Grid

https://codeforces.com/contest/1557/problem/D

線段樹維護dp + dp路徑記錄 + 離散化
考慮最多能保留的個數,線段樹維護相鄰兩層間轉移的1的位置的最大值.
對每層考慮,新加進來一個線段,都會產生一個非負的貢獻,每次轉移都要詢問這一層能向上轉移的每個點的最大值同時記錄轉移到上一層的id


const int maxn = 6e5 + 7;

int n, t, m;

struct node {
    int l, r, mx, id, lz;
} tr[maxn << 2];

void push_up(int p) {
    if (tr[p << 1].mx >= tr[p << 1 | 1].mx) {
        tr[p].mx = tr[p << 1].mx;
        tr[p].id = tr[p << 1].id;
    } else {
        tr[p].mx = tr[p << 1 | 1].mx;
        tr[p].id = tr[p << 1 | 1].id;
    }
}

void push_down(int p) {
    if (tr[p].lz != -1) {
        tr[p << 1].lz = tr[p << 1 | 1].lz = tr[p].lz;
        tr[p << 1].mx = tr[p << 1 | 1].mx = tr[p].lz;
        tr[p << 1].id = tr[p << 1 | 1].id = tr[p].id;
        tr[p].lz = -1;
    }
}

void build(int p, int l, int r) {
    tr[p].l = l, tr[p].r = r, tr[p].lz = -1;
    if (l == r) {
        tr[p].id = 0;
        tr[p].mx = 0;
        return;
    }
    int mi = (l + r) >> 1;
    build(p << 1, l, mi);
    build(p << 1 | 1, mi + 1, r);
    push_up(p);
}

void update(int p, int l, int r, int val, int id) {
    if (l <= tr[p].l && tr[p].r <= r) {
        tr[p].mx = val;
        tr[p].id = id;
        tr[p].lz = val;
        return;
    }
    push_down(p);
    int mi = (tr[p].l + tr[p].r) >> 1;
    if (l <= mi) update(p << 1, l, r, val, id);
    if (r > mi) update(p << 1 | 1, l, r, val, id);
    push_up(p);
}

int mx, pos;

void query(int p, int l, int r) {
    if (l <= tr[p].l && tr[p].r <= r) {
        if (tr[p].mx >= mx) {
            mx = tr[p].mx;
            pos = tr[p].id;
        }
        return;
    }
    push_down(p);
    int mi = (tr[p].l + tr[p].r) >> 1;
    if (l <= mi) query(p << 1, l, r);
    if (r > mi) query(p << 1 | 1, l, r);
}

set<int> st;
map<int, int> mp;
int cnt = 0;

int id[maxn], ls[maxn], rs[maxn];
int dp[maxn], pre[maxn];
vector<pair<int, int>> vec[maxn];

void solve() {
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        cin >> id[i] >> ls[i] >> rs[i];
        st.insert(ls[i]), st.insert(rs[i]);
    }
    for (auto i:st) mp[i] = ++cnt;
    for (int i = 1; i <= m; i++)
        vec[id[i]].emplace_back(mp[ls[i]], mp[rs[i]]);
    build(1, 1, (int) st.size() + 1);
    for (int i = 1; i <= n; i++) {
        for (auto s:vec[i]) {
            int l = s.first, r = s.second;
            mx = 0, pos = -1;
            query(1, l, r);
            if (mx + 1 > dp[i]) {
                dp[i] = mx + 1;
                pre[i] = pos;
            }
        }
        for (auto s:vec[i]) {
            int l = s.first, r = s.second;
            update(1, l, r, dp[i], i);
        }
    }
    int mx_p = max_element(dp + 1, dp + 1 + n) - dp;
    set<int> res;
    
    for (int i = 1; i <= n; i++)
        res.insert(i);
    while (mx_p) {
        res.erase(mx_p);
        mx_p = pre[mx_p];
    }
    cout << res.size() << endl;
    for (auto i :res)
        cout << i << " ";
}
我看見 你