CF1557D Ezzat and Grid 解题报告
首先把 \(l,r\) 离散化掉,注意数组大小。
设 \(f_i\) 表示以第 \(i\) 行结尾,能保留的最大行数,\(f_i=\max\{f_j\}+1\),其中 \(i\) 和 \(j\) 存在一个相同位置都被覆盖。
更进一步地,设 \(g_i\) 表示位置 \(i\) 上被线段覆盖时的最大的 \(f\) 值,那么 \(f_i\) 就等于所有第 \(i\) 行线段对应区间的 \(g\) 值的 \(\max\) 再加一,然后把 \(f_i\) 贡献到它对应的区间上,这个贡献直观感受是让区间对 \(f_i\) 取 \(\max\)。
但不难发现对于一个 \(i\),每次更新时 \(g_i\) 是单调递增的,即如果这个位置 \(i\) 在 \(f_j\) 更新时被涉及,那么有 \(f_j>g_i\),所以实际上区间取 \(\max\) 的操作改为区间赋值即可。
需要用线段树实现区间赋值,区间查询 \(\max\),方案的话把结点记录的信息改为 pair 即可。
#include<bits/stdc++.h>
using namespace std;
int n,m;
#define mp make_pair
vector<pair<int,int>> Col[300005];
int C[300005],L[300005],R[300005],b[600005],pre[300005];
bool vis[300005];
pair<int,int> maxn[10800005],tag[10800005];
#define lc(x) (x<<1)
#define rc(x) (lc(x)|1)
#define Mm int mid=(l+r)>>1
pair<int,int> Max(pair<int,int> x,pair<int,int> y)
{
if(x.first>y.first) return x;
return y;
}
void push_down(int now)
{
tag[lc(now)]=Max(tag[lc(now)],tag[now]);
tag[rc(now)]=Max(tag[rc(now)],tag[now]);
maxn[lc(now)]=Max(maxn[lc(now)],tag[now]);
maxn[rc(now)]=Max(maxn[rc(now)],tag[now]);
tag[now].first=0;
}
void push_up(int now){maxn[now]=Max(maxn[lc(now)],maxn[rc(now)]);}
void modify(int l,int r,int now,int x,int y,pair<int,int> val)
{
if(x<=l && r<=y)
{
tag[now]=Max(tag[now],val);
maxn[now]=Max(maxn[now],val);
return ;
}
push_down(now);
Mm;
if(x<=mid) modify(l,mid,lc(now),x,y,val);
if(mid<y) modify(mid+1,r,rc(now),x,y,val);
push_up(now);
}
pair<int,int> query(int l,int r,int now,int x,int y)
{
if(x<=l && r<=y) return maxn[now];
push_down(now);
Mm;
pair<int,int> ret;
ret.first=0;
if(x<=mid) ret=max(ret,query(l,mid,lc(now),x,y));
if(mid<y) ret=max(ret,query(mid+1,r,rc(now),x,y));
return ret;
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=m;++i)
{
scanf("%d %d %d",&C[i],&L[i],&R[i]);
b[i*2-1]=L[i],b[i*2]=R[i];
}
sort(b+1,b+1+m+m);
int len=unique(b+1,b+1+m+m)-b-1;
for(int i=1;i<=m;++i)
{
L[i]=lower_bound(b+1,b+1+len,L[i])-b;
R[i]=lower_bound(b+1,b+1+len,R[i])-b;
Col[C[i]].push_back(mp(L[i],R[i]));
}
for(int i=1;i<=n;++i)
{
int dp=0;
for(auto st:Col[i]) dp=max(dp,query(1,len,1,st.first,st.second).first);
for(auto st:Col[i])
{
pair<int,int> que=query(1,len,1,st.first,st.second);
if(que.first==dp)
{
pre[i]=que.second;
break;
}
}
++dp;
for(auto st:Col[i]) modify(1,len,1,st.first,st.second,mp(dp,i));
}
printf("%d\n",n-maxn[1].first);
int now=maxn[1].second;
while(now)
{
vis[now]=true;
now=pre[now];
}
for(int i=1;i<=n;++i) if(!vis[i]) printf("%d ",i);
return 0;
}

浙公网安备 33010602011771号