Codeforces Round #737 (Div. 2) D. Ezzat and Grid
线段树维护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 << " ";
}
我看见 你