题解 CF1557D 【Ezzat and Grid】
registerGen · · 题解
这次比赛的题解
dp。设
转移的时候考虑所有值为
这个可以用线段树优化。具体的,对于每个
具体细节见代码(非 C++11 党勿入):
using ll=long long;
using pii=std::pair<int,int>;
// 区间覆盖,区间 max,还要维护方案
struct SegTree{
struct Node{
pii mx,ctag;
};
std::vector<Node> t;
SegTree(int n=0){
t.resize(n*4+5,{{0,-1},{0,-1}});
}
std::function<int(int)> ls=[](int x)->int{return x<<1;};
std::function<int(int)> rs=[](int x)->int{return x<<1|1;};
std::function<Node(const Node &,const Node &)> pushUp=[](const Node &L,const Node &R)->Node{
return {std::max(L.mx,R.mx),{0,-1}};
};
std::function<void(Node &,const pii &)> pushC=[](Node &now,const pii &ctag)->void{
now.mx=now.ctag=ctag;
};
std::function<void(int)> pushDown=[this](int i)->void{
if(t[i].ctag!=pii({0,-1})){
pushC(t[ls(i)],t[i].ctag);
pushC(t[rs(i)],t[i].ctag);
t[i].ctag={0,-1};
}
};
std::function<void(int,int,int,int,int,const pii &)> modify=[this](int i,int l,int r,int ql,int qr,const pii &x)->void{
if(ql<=l&&r<=qr)return pushC(t[i],x),void();
int mid=(l+r)>>1;
pushDown(i);
if(ql<=mid)modify(ls(i),l,mid,ql,qr,x);
if(qr>mid) modify(rs(i),mid+1,r,ql,qr,x);
t[i]=pushUp(t[ls(i)],t[rs(i)]);
};
std::function<Node(int,int,int,int,int)> query=[this](int i,int l,int r,int ql,int qr)->Node{
if(ql<=l&&r<=qr)return t[i];
int mid=(l+r)>>1;
pushDown(i);
if(ql>mid) return query(rs(i),mid+1,r,ql,qr);
if(qr<=mid)return query(ls(i),l,mid,ql,qr);
return pushUp(query(ls(i),l,mid,ql,qr),query(rs(i),mid+1,r,ql,qr));
};
};
void mian(){
int n,m;
scanf("%d%d",&n,&m);
std::vector<std::vector<pii>> a(n);
for(int i=0;i<m;i++){
int p,l,r;
scanf("%d%d%d",&p,&l,&r);
p--;
a[p].push_back({l,r});
}
// 把所有线段离散化
std::function<void(void)> init=[&]()->void{
std::vector<int> tmp;
for(auto i:a)
for(auto j:i)
tmp.push_back(j.first),tmp.push_back(j.second);
std::sort(tmp.begin(),tmp.end());
auto it=std::unique(tmp.begin(),tmp.end());
tmp.erase(it,tmp.end());
for(auto &i:a)
for(auto &j:i){
j.first=std::lower_bound(tmp.begin(),tmp.end(),j.first)-tmp.begin()+1;
j.second=std::lower_bound(tmp.begin(),tmp.end(),j.second)-tmp.begin()+1;
}
};
init();
std::vector<pii> f(n);
for(auto &x:f)x.second=-1;
SegTree t(m*2);
for(int i=0;i<n;i++){
for(auto j:a[i]){ // 枚举第 i 行所有的值为 1 的格子
auto x=t.query(1,1,m*2,j.first,j.second); // max_{k=1..i-1,grid[k][j]}=1} f[j]
x.mx.first++;
f[i]=std::max(f[i],x.mx);
}
for(auto j:a[i])
t.modify(1,1,m*2,j.first,j.second,{f[i].first,i}); // 更新 max f[k][j]
}
// 输出方案
int p=0;
for(int i=0;i<n;i++)
if(f[i]>f[p])p=i;
std::set<int> ans;
for(int i=0;i<n;i++)ans.insert(i);
for(;p!=-1;p=f[p].second)ans.erase(p);
printf("%d\n",int(ans.size()));
for(auto i:ans)printf("%d ",i+1);
puts("");
}