Codeforces Round #737 (Div. 2) Ezzat and Grid(线段树优化dp)
Posted thusloop
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #737 (Div. 2) Ezzat and Grid(线段树优化dp)相关的知识,希望对你有一定的参考价值。
题目地址:Ezzat and Grid
Moamen was drawing a grid of n rows and 109 columns containing only digits 0 and 1. Ezzat noticed what Moamen was drawing and became interested in the minimum number of rows one needs to remove to make the grid beautiful.
A grid is beautiful if and only if for every two consecutive rows there is at least one column containing 1 in these two rows.
Ezzat will give you the number of rows n, and m segments of the grid that contain digits 1. Every segment is represented with three integers i, l, and r, where i represents the row number, and l and r represent the first and the last column of the segment in that row.
For example, if n=3, m=6, and the segments are (1,1,1), (1,7,8), (2,7,7), (2,15,15), (3,1,1), (3,15,15), then the grid is:
Your task is to tell Ezzat the minimum number of rows that should be removed to make the grid beautiful.
思路:dp[i][j] 为 i 行之前删除一些行之后满足条件的最大行数, j为这一行中有1的状态
要寻找当前行中满足条件的最大行数 如果当前行中有1的状态和前面行中有1的状态相交 ,当前行=前面与当前1相交的行的最大值 +1
可以用线段树维护区间最大值
#include<bits/stdc++.h>
//#define int long long
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
//const int inf=2e18+100;
const int maxn=1e6+100;
typedef pair<int,int> pii;
struct node//线段树维护区间最大值,顺便保存行号;
{
int l,r;
pii sum;
pii lazy;
//int c;
} t[maxn*4];
struct node1
{
int c,l,r;
} t1[maxn];
vector<pii>g[maxn];
pii Max(pii a,pii b)
{
if(a.first>b.first)return a;
return b;
}
void pushup(int k)
{
t[k].sum=Max(t[k<<1].sum,t[k<<1|1].sum);
}
void pushdown(int k)
{
if(t[k].lazy.first)
{
t[k<<1|1].lazy=t[k].lazy;
t[k<<1].lazy=t[k].lazy;
t[k<<1|1].sum=t[k].lazy;
t[k<<1].sum=t[k].lazy;
t[k].lazy={0,0};
}
}
void build(int k,int l,int r)
{
t[k].l=l;
t[k].r=r;
if(l==r)return ;
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pushup(k);
}
void update(int l,int r,int k,pii p)
{
if(l>t[k].r||r<t[k].l)return ;
if(l<=t[k].l&&t[k].r<=r)
{
t[k].sum=p;
t[k].lazy=p;
return ;
}
pushdown(k);
update(l,r,k<<1,p);
update(l,r,k<<1|1,p);
pushup(k);
}
pii query(int l,int r,int k)
{
if(r<t[k].l||l>t[k].r)return {0,0};
if(l<=t[k].l&&t[k].r<=r)
{
return t[k].sum;
}
pushdown(k);
return Max(query(l,r,k<<1|1),query(l,r,k<<1));
}
map<int,int>mp;
int pre[maxn];//保存前驱
bool vis[maxn];
signed main()
{
IOS
int n,m;
cin>>n>>m;
for(int i=1; i<=m; i++)
{
int c,l,r;
cin>>c>>l>>r;
mp[l]=1;
mp[r]=1;
t1[i]= {c,l,r};
}
int k=0;
for(auto it:mp)
{
mp[it.first]=++k;//离散化
}
build(1,1,k);
for(int i=1; i<=m; i++)
{
int x=mp[t1[i].l];
int y=mp[t1[i].r];
g[t1[i].c].push_back({x,y});
}
int ans=0,fg=0;//最大的值和取得最大值的行
for(int i=1; i<=n; i++)
{
int now=-1;
for(auto it:g[i])
{
pii p=query(it.first,it.second,1);//查询i之前该区间的最大值
if(p.first>now)
{
now=p.first;
pre[i]=p.second;
}
}
if(now+1>ans)//更新最大值
{
ans=now+1;
fg=i;
}
for(auto it:g[i])
{
update(it.first,it.second,1, {now+1,i});//更新i行的区间
}
}
cout<<n-ans<<"\\n";
for(int i=fg; i != 0; i = pre[i]) vis[i] = 1;
for(int i=1; i<=n; i++)
{
if(vis[i]==0)
{
cout<<i<<" ";
}
}
}
以上是关于Codeforces Round #737 (Div. 2) Ezzat and Grid(线段树优化dp)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #737 (Div. 2) 题解
Codeforces Round #737 (Div. 2) 题解
Codeforces Round #737 (Div. 2) 题解
Codeforces Round #737 (Div. 2) Ezzat and Grid(线段树优化dp)