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;
}

浙公网安备 33010602011771号