CF1557 D. Ezzat and Grid(dp+線段樹)
阿新 • • 發佈:2021-09-03
目錄
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; }