总结收获
- 最重要的是知道怎么解决的,代码实在现在写不出来,可以先借鉴一下大佬的hhh。
题目
传送门
- 题意:n*1e9的01阵,m条线段(i,l,r)表示第i行[l,r]都为1,线段可能重复。一个漂亮矩阵定义为任意连续两行都至少有一列在这两行中都为1,求最少删去多少行,能使剩下的矩阵为漂亮矩阵。
- 题解:不难想到,遍历每一行,每一行的上面一行应该是行数最多的漂亮矩阵的最后一行,然后线段树维护即可(具体的看代码)
2.1 离散化:用unique
而不用map
。
2.2 pair<int,int>
:能用就用,不用自己搞个结构体(大佬都在用pair),另外{x,y}
似乎可以等价于make_pair(x,y)
。
2.3 for(auto &i:g[x])
:然后才可以修改值,否则知识取数操作。
2.4 emplace_back
算是puah_back
的优化。 - 代码:
#include <bits/stdc++.h>
#define pii pair<int, int>
#define dbg(x) cout << #x << "===" << x << endl
using namespace std;
const int N = 6e5 + 5;
int n, m, p, l, r;
int f[N], vis[N];
vector<pii> v[N];
vector<int> x;
pii mx[N << 2], tag[N << 2];
void pushdown(int p) {
mx[p << 1] = max(mx[p << 1], tag[p]);
mx[p << 1 | 1] = max(mx[p << 1 | 1], tag[p]);
tag[p << 1] = max(tag[p << 1], tag[p]);
tag[p << 1 | 1] = max(tag[p << 1 | 1], tag[p]);
tag[p] = {0, 0};
}
void update(int p, int l, int r, int x, int y, pii k) {
if (x <= l && r <= y) {
mx[p] = max(mx[p], k), tag[p] = max(tag[p], k);
return;
}
pushdown(p);
int mid = (l + r) >> 1;
if (mid >= x) update(p << 1, l, mid, x, y, k);
if (mid < y) update(p << 1 | 1, mid + 1, r, x, y, k);
mx[p] = max(mx[p << 1], mx[p << 1 | 1]);
}
pii query(int p, int l, int r, int x, int y) {
if (x <= l && r <= y) return mx[p];
pushdown(p);
pii res = {0, 0};
int mid = (l + r) >> 1;
if (mid >= x) res = max(res, query(p << 1, l, mid, x, y));
if (mid < y) res = max(res, query(p << 1 | 1, mid + 1, r, x, y));
return res;
}
int get(int &t) {
return t = lower_bound(x.begin(), x.end(), t) - x.begin() + 1;
}
void solve() {
cin >> n >> m;
int i, j;
for (i = 1; i <= m; i++) {
cin >> p >> l >> r;
v[p].push_back({l, r});
x.emplace_back(l), x.emplace_back(r);
}
sort(x.begin(), x.end());
x.resize(unique(x.begin(), x.end()) - x.begin());
int k = x.size() - 1;
pii ans = {0, 0};
int L, R;
for (i = 1; i <= n; i++) {
pii y = {0, 0};
for (auto &j : v[i]) {
L = get(j.first), R = get(j.second);
y = max(y, query(1, 1, k + 2, L, R));
}
y.first++;
f[i] = y.second;
y.second = i;
ans = max(ans, y);
for (auto j : v[i]) {
L = j.first, R = j.second;
update(1, 1, k + 2, L, R, y);
}
}
cout << n - ans.first << "\n";
for (i = ans.second; i; i = f[i]) vis[i] = 1;
for (i = 1; i <= n; i++)
if (!vis[i]) cout << i << " ";
}
signed main() {
int T = 1;
while (T--) {
solve();
}
return 0;
}