cf1557D. Ezzat and Grid

Posted Jozky86

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cf1557D. Ezzat and Grid相关的知识,希望对你有一定的参考价值。

cf1557D. Ezzat and Grid

题意:

有n行,每行有 1 0 9 10^9 109列,仅仅由0和1构成
现在给你1的存在位置,(i,l,r)表示第i行的第l列到第r列全为1
你可以删除任意一行i,删除后,第i-1行和第i+1行为相邻
现在我们要求求最多的行数,使得每个相邻两行最少有一列都是1(可以理解成上下相邻1),并输出删除了哪些行

题解:

对于i行,我们考虑前i-1行个是与i行满足要求的(即存在相邻1)。我们用线段树维护一个pair<int,int>sum
sum.first表示以id为结尾所保留的最大行数
sum.second=id:表示以id为结尾的情况
因为1的出现都是连续的,我们想查找与第i行满足情况的行数,就在第i行出现1的区间(例如[l,r]),我们就查看所有[l,r]区间内的值,取最大值得到sum(相当于取之前的最大值接着当前的i)。sum为与第i行满足情况且保留行数最多的某一行。查询完后,要将第i行的情况插入到线段树中,在区间[l,r]中插入我们的ans(ans.second=i,ans.first=sum.first+1)
为了方便输出,我们用一个path来实现记录路径
讲的可以不是很明白,详细可以看看代码

代码:

改了一个多小时,终于改出来了

// 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
// Data:2021-08-23 15:24:28
// By Jozky

#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
void read(){};
template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar)
{
    x= 0;
    char c= getchar();
    bool flag= 0;
    while (c < '0' || c > '9')
        flag|= (c == '-'), c= getchar();
    while (c >= '0' && c <= '9')
        x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();
    if (flag)
        x= -x;
    read(Ar...);
}
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');
}
void rd_test()
{
#ifdef LOCAL
    startTime= clock();
    freopen("in.txt", "r", stdin);
#endif
}
void Time_test()
{
#ifdef LOCAL
    endTime= clock();
    printf("\\nRun Time:%lfs\\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
const int maxn= 1e6 + 9;
vector<PII> vec[maxn];
int num[maxn];
int tot= 0;
struct tree
{
    int l, r;
    int lazy= 0;
    PII maxx;
} tr[maxn << 2];
void pushup(int rt)
{
    tr[rt].maxx= max(tr[rt << 1].maxx, tr[rt << 1 | 1].maxx);
}
void solve(int rt, PII val)
{
    tr[rt].maxx= val;
    tr[rt].lazy= 1;
}
void pushdown(int rt)
{
    if (tr[rt].lazy == 0)
        return;
    solve(rt << 1, tr[rt].maxx);
    solve(rt << 1 | 1, tr[rt].maxx);
    tr[rt].lazy= 0;
}
void build(int rt, int l, int r)
{
    tr[rt].l= l;
    tr[rt].r= r;
    tr[rt].lazy= 0;
    tr[rt].maxx= {0, -1};
    if (l == r) {
        return;
    }
    int mid= (l + r) >> 1;
    build(rt << 1, l, mid);
    build(rt << 1 | 1, mid + 1, r);
    pushup(rt);
}
void update(int rt, int l, int r, PII x)
{
    if (tr[rt].r < l || tr[rt].l > r)
        return;
    if (tr[rt].l >= l && tr[rt].r <= r) {
        solve(rt, x);
        return;
    }
    //if (tr[rt].lazy)
    pushdown(rt);
    int mid= (tr[rt].l + tr[rt].r) >> 1;

    update(rt << 1, l, r, x);
    update(rt << 1 | 1, l, r, x);
    pushup(rt);
}
PII query(int rt, int l, int r)
{
    if (tr[rt].r < l || tr[rt].l > r)
        return {0, -1};
    if (tr[rt].l >= l && tr[rt].r <= r) {
        return tr[rt].maxx;
    }
    //if (tr[rt].lazy)
    pushdown(rt);
    int mid= (tr[rt].l + tr[rt].r) >> 1;

    PII maxx= {0, -1};
    maxx= max(maxx, max(query(rt << 1, l, r), query(rt << 1 | 1, l, r)));
    return maxx;
}
int path[maxn];
int ans[maxn];
int main()
{
    //rd_test();
    int n, m;
    read(n, m);
    for (int i= 1; i <= m; i++) {
        int id, l, r;
        read(id, l, r);
        vec[id].push_back({l, r});
        num[++tot]= l;
        num[++tot]= r;
    }
    sort(num + 1, num + 1 + tot);
    int cnt= unique(num + 1, num + 1 + tot) - num - 1;
    // cout << "cnt=" << cnt << endl;
    for (int i= 1; i <= n; i++) {
        for (int j= 0; j < vec[i].size(); j++) {
            // printf("vec[i][j]=%d \\n", vec[i][j]);
            vec[i][j].first= lower_bound(num + 1, num + 1 + cnt, vec[i][j].first) - num;
            vec[i][j].second= lower_bound(num + 1, num + 1 + cnt, vec[i][j].second) - num;
            // printf("处理后vec[i][j]=%d\\n ", vec[i][j]);
        }
    }
    build(1, 1, cnt);
    //cout << "--" << endl;
    PII maxx;
    for (int i= 1; i <= n; i++) {
        maxx= {0, -1};
        //保存的数量  编号
        for (auto it : vec[i]) {
            // printf("l=%d r=%d\\n", it.first, it.second);
            maxx= max(maxx, query(1, it.first, it.second));
        }
        path[i]= maxx.second;
        PII ans= {maxx.first + 1, i};
        for (auto it : vec[i]) {
            // printf("l=%d r=%d\\n", it.first, it.second);
            update(1, it.first, it.second, ans);
        }
    }
    maxx= query(1, 1, cnt);
    printf("%d\\n", n - maxx.first);
    int now= maxx.second;
    while (now != -1) {
        ans[now]= 1;
        now= path[now];
    }
    for (int i= 1; i <= n; i++) {
        if (!ans[i])
            printf("%d ", i);
    }
    return 0;
    //Time_test();
}


以上是关于cf1557D. Ezzat and Grid的主要内容,如果未能解决你的问题,请参考以下文章

CF 1557D(Ezzat and Grid-线段覆盖)

CF 1557D(Ezzat and Grid-线段覆盖)

CodeForces - 1557D Ezzat and Grid(线段树+dp)

Codeforces Round #737 (Div. 2) D. Ezzat and Grid 线段树模拟最长上升子序列

Codeforces Round #737 (Div. 2) Ezzat and Grid(线段树优化dp)

CF #737(div2)A. Ezzat and Two Subsequences,贪心