CodeForces - 1557D Ezzat and Grid(线段树+dp)
Posted Frozen_Guardian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces - 1557D Ezzat and Grid(线段树+dp)相关的知识,希望对你有一定的参考价值。
题目链接:点击查看
题目大意:给出 n n n 个 01 01 01 串,现在问最少需要删掉多少个串,才能使得剩下的串拼起来是连通的
规定两个 01 01 01 串是连通的,当且仅当存在至少一列,在两个串中都为 1 1 1
题目分析:正难则反,题目要求删除最少,那么我们思考如何使得保留下来的串最多。考虑 d p [ i ] dp[i] dp[i] 为以第 i i i 个序列为结尾的,可以保留的最多的串的个数,模仿最长不下降子序列的思路, d p [ i ] = d p [ j ] + 1 dp[i]=dp[j]+1 dp[i]=dp[j]+1,当且仅当串 i i i 和串 j j j 是可以连通的,在本题中判断两个串是否连通,可以用线段树判断是否存在区间交即可
其实更简单的,因为我们转移 d p dp dp 时是线性递推的过程,假如对于第 i i i 个串来说,存在区间 [ l , r ] [l,r] [l,r] 都是 1 1 1 的序列,那么不难看出与区间 [ l , r ] [l,r] [l,r] 存在交集的 j j j 串都是可以转移的,但是我们只需要最大值就可以了,所以线段树实际上维护一下区间 [ l , r ] [l,r] [l,r] 内最大的 d p dp dp 值就可以了
需要注意的是区间特别大,所以需要离散化一下,动态开点好像会被卡常,输出答案的时候可以转换为 dp 的路径输出问题
代码:
// Problem: D. Ezzat and Grid
// Contest: Codeforces - Codeforces Round #737 (Div. 2)
// URL: https://codeforces.com/contest/1557/problem/D
// Memory Limit: 256 MB
// Time Limit: 2500 ms
//
// Powered by CP Editor (https://cpeditor.org)
// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#define lowbit(x) x&-x
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{
T f=1;x=0;
char ch=getchar();
while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
x*=f;
}
template<typename T>
inline void write(T x)
{
if(x<0){x=~(x-1);putchar('-');}
if(x>9)write(x/10);
putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=1e6+100;
vector<pair<int,int>>node[N];
int dp[N],pre[N];
bool ban[N];
struct Node {
int l,r,mmax,lazy;
}tree[N<<2];
void pushup(int k) {
tree[k].mmax=dp[tree[k<<1].mmax]>dp[tree[k<<1|1].mmax]?tree[k<<1].mmax:tree[k<<1|1].mmax;
}
void pushdown(int k) {
if(tree[k].lazy) {
int lz=tree[k].lazy;
tree[k].lazy=0;
tree[k<<1].lazy=tree[k<<1|1].lazy=lz;
tree[k<<1].mmax=tree[k<<1|1].mmax=lz;
}
}
void build(int k,int l,int r) {
if(l>r) {
return;
}
tree[k]={l,r,0,0};
if(l==r) {
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
}
void update(int k,int l,int r,int val) {
if(tree[k].l>r||tree[k].r<l) {
return;
}
if(tree[k].l>=l&&tree[k].r<=r) {
tree[k].mmax=val;
tree[k].lazy=val;
return;
}
pushdown(k);
update(k<<1,l,r,val);
update(k<<1|1,l,r,val);
pushup(k);
}
int query(int k,int l,int r) {
if(tree[k].l>r||tree[k].r<l) {
return 0;
}
if(tree[k].l>=l&&tree[k].r<=r) {
return tree[k].mmax;
}
pushdown(k);
int ans1=query(k<<1,l,r),ans2=query(k<<1|1,l,r);
if(dp[ans1]>dp[ans2]) {
return ans1;
} else {
return ans2;
}
}
vector<int>dis;
int get_id(int x) {
return lower_bound(dis.begin(),dis.end(),x)-dis.begin()+1;
}
void discreate() {
sort(dis.begin(),dis.end());
dis.erase(unique(dis.begin(),dis.end()),dis.end());
for(int i=1;i<N;i++) {
for(auto &it:node[i]) {
it.first=get_id(it.first),it.second=get_id(it.second);
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
// freopen("data.in.txt","r",stdin);
// freopen("data.out.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);
int n,m;
read(n),read(m);
for(int i=1;i<=m;i++) {
int id,l,r;
read(id),read(l),read(r);
node[id].push_back({l,r});
dis.push_back(l),dis.push_back(r);
}
discreate();
build(1,1,dis.size());
dp[0]=0,pre[0]=-1;
for(int i=1;i<=n;i++) {
dp[i]=1,pre[i]=0;
for(auto it:node[i]) {
int l=it.first,r=it.second;
int p=query(1,l,r);
if(dp[p]+1>dp[i]) {
dp[i]=dp[p]+1;
pre[i]=p;
}
}
for(auto it:node[i]) {
int l=it.first,r=it.second;
update(1,l,r,i);
}
}
int mmax=*max_element(dp+1,dp+1+n);
for(int i=1;i<=n;i++) {
if(mmax==dp[i]) {
int pos=i;
while(pos!=-1) {
ban[pos]=true;
pos=pre[pos];
}
break;
}
}
vector<int>ans;
for(int i=1;i<=n;i++) {
if(!ban[i]) {
ans.push_back(i);
}
}
cout<<ans.size()<<endl;
for(auto it:ans) {
cout<<it<<' ';
}
cout<<endl;
return 0;
}
以上是关于CodeForces - 1557D Ezzat and Grid(线段树+dp)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #737 (Div. 2) Ezzat and Grid(线段树优化dp)
Codeforces Round #737 (Div. 2) D. Ezzat and Grid 线段树模拟最长上升子序列
Codeforces Round #737 (Div. 2) D. Ezzat and Grid(线段树,dp)