• Codeforces


    题意:

      给出n行,109列的01矩阵,矩阵中的1是由m段连续的横向区间构成。问至少删除多少行,使得剩下的任意两行之间至少有同一列都为1;并输出删除方案。

    题解:

      假定某两行有同一列是1,那么称这两行相连。

      即使有109列,但是成段的1也只有m段而已。

      总体是dp的思想:从上往下扫每一行,当前行的答案是它上面和它相连的行的答案的最大值+1

      用线段树优化dp,维护每个区间的答案最大值以及最大值时的行号。

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 3e5+10;
    typedef pair<int, int> P;
    int n, m, tot;
    int p, l, r;
    int last[N];
    int visit[N];
    vector<int> v;
    vector<P> g[N];
    P lzy[N<<4], tree[N<<4];
    
    int get_pos(int x) {
        return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
    }
    
    void push_up(int id) {
        P val = max(tree[id<<1], tree[id<<1|1]);
        tree[id] = max(tree[id], val);
    }
    
    void push_down(int id) {
        if(lzy[id].first == 0)
            return;
        lzy[id<<1] = max(lzy[id<<1], lzy[id]);
        lzy[id<<1|1] = max(lzy[id<<1|1], lzy[id]);
        tree[id<<1] = max(tree[id<<1], lzy[id]);
        tree[id<<1|1] = max(tree[id<<1|1], lzy[id]);
        lzy[id] = make_pair(0, 0);
    }
    
    void insert(int id, int l, int r, int ql, int qr, P val) {
        if(ql <= l && r <= qr) {
            tree[id] = max(tree[id], val);
            lzy[id] = max(lzy[id], val);
            return;
        }
        push_down(id);
        int mid = (l + r) >> 1;
        if(ql <= mid) insert(id<<1, l, mid, ql, qr, val);
        if(qr > mid) insert(id<<1|1, mid+1, r, ql, qr, val);
        push_up(id);
    }
    
    P query(int id, int l, int r, int ql, int qr) {
        if(ql <= l && r <= qr) {
            return tree[id];
        }
        push_down(id);
        int mid = (l + r) >> 1;
        P now = make_pair(0, 0);
        if(ql <= mid) now = query(id<<1, l, mid, ql, qr);
        if(qr > mid) now = max(now, query(id<<1|1, mid+1, r, ql, qr));
        push_up(id);
        return now;
    }
    
    int main() {
        scanf("%d%d", &n, &m);
        while(m--) {
            scanf("%d%d%d", &p, &l, &r);
            g[p].push_back(make_pair(l, r));
            v.push_back(l);
            v.push_back(r);
        }
    
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
        tot = v.size();
    
        P ans = make_pair(0, 0);
        for(int i = 1; i <= n; i++) {
            P res = make_pair(0, 0);
            for(int j = 0; j < g[i].size(); j++) {
                l = get_pos(g[i][j].first);
                r = get_pos(g[i][j].second);
                res = max(res, query(1, 1, tot, l, r));
            }
    
            last[i] = res.second;
            res.first++;
            res.second = i;
            ans = max(ans, res);
    
            for(int j = 0; j < g[i].size(); j++) {
                l = get_pos(g[i][j].first);
                r = get_pos(g[i][j].second);
                insert(1, 1, tot, l, r, res);
            }
        }
    
        int pos = ans.second;
        while(pos) {
            visit[pos] = 1;
            pos = last[pos];
        }
        printf("%d
    ", n - ans.first);
        bool flag = false;
        for(int i = 1; i <= n; i++) {
            if(!visit[i]) {
                if(flag)
                    printf(" ");
                flag = true;
                printf("%d", i);
            }
        }
    }
    C++
    package main
    import (
        "io"
        "os"
        "fmt"
        "sort"
        "bufio"
    )
    const N int = 3e5+10
    var n, m, tot int
    var p, l, r int
    var last, visit [N]int
    var v sort.IntSlice
    var g [][]pair
    var lzy, tree [N<<4]pair
    type pair struct {
        first, second int
    }
    
    func max(x, y pair) pair {
        if x.first > y.first {
            return x
        }
        if x.first == y.first {
            if x.second > y.second {
                return x
            }
        }
        return y
    }
    
    func get_pos(x int) int {
        l := 0
        r := tot - 1
        for l <= r {
            mid := (l + r) >> 1
            if v[mid] < x {
                l = mid + 1
            } else {
                r = mid - 1
            }
        }
        return l + 1
    }
    
    func push_up(id int) {
        val := max(tree[id<<1], tree[id<<1|1])
        tree[id] = max(tree[id], val)
    }
    
    func push_down(id int) {
        if lzy[id].first == 0 {
            return
        }
        lzy[id<<1] = max(lzy[id<<1], lzy[id])
        lzy[id<<1|1] = max(lzy[id<<1|1], lzy[id])
        tree[id<<1] = max(tree[id<<1], lzy[id])
        tree[id<<1|1] = max(tree[id<<1|1], lzy[id])
        lzy[id] = pair{0, 0}
    }
    
    func insert(id, l, r, ql, qr int, val pair) {
        if ql <= l && r <= qr {
            tree[id] = max(tree[id], val)
            lzy[id] = max(lzy[id], val)
            return
        }
        push_down(id)
        mid := (l + r) >> 1
        if ql <= mid {
            insert(id<<1, l, mid, ql, qr, val)
        }
        if qr > mid {
            insert(id<<1|1, mid+1, r, ql, qr, val)
        }
        push_up(id)
    }
    
    func query(id, l, r, ql, qr int) pair {
        if ql <= l && r <= qr {
            return tree[id]
        }
        push_down(id)
        mid := (l + r) >> 1
        now := pair{0, 0}
        if ql <= mid {
            now = query(id<<1, l, mid, ql, qr)
        }
        if qr > mid {
            now = max(now, query(id<<1|1, mid+1, r, ql, qr))
        }
        push_up(id)
        return now
    }
    
    func main() {
        var input io.Reader = bufio.NewReader(os.Stdin)
        
        fmt.Fscan(input, &n)
        for i := 1; i <= n + 1; i++ {
            tmp := []pair{}
            g = append(g, tmp)
        }
    
        for fmt.Fscan(input, &m); m > 0; m-- {
            fmt.Fscan(input, &p)
            fmt.Fscan(input, &l)
            fmt.Fscan(input, &r)
            g[p] = append(g[p], pair{l, r})
            v = append(v, l, r)
        }
    
        sort.Ints(v)
        l = 0
        for i, _ := range v {
            if i == 0 || v[i] != v[i-1] {
                v[l] = v[i]
                l++
            }
        }
        v = v[0:l]
        tot = len(v)
    
        ans := pair{0, 0}
        for i := 1; i <= n; i++ {
            res := pair{0, 0}
            for _, val := range g[i] {
                l = get_pos(val.first)
                r = get_pos(val.second)
                res = max(res, query(1, 1, tot, l, r))
            }
    
            last[i] = res.second
            res.first++
            res.second = i
            ans = max(ans, res)
    
            for _, val := range g[i] {
                l = get_pos(val.first)
                r = get_pos(val.second)
                insert(1, 1, tot, l, r, res)
            }
        }
    
        pos := ans.second
        for pos > 0 {
            visit[pos] = 1
            pos = last[pos]
        }
        fmt.Println(n - ans.first)
        flag := false
        for i := 1; i <= n; i++ {
            if visit[i] == 0 {
                if flag {
                    fmt.Print(" ")
                }
                flag = true
                fmt.Print(i)
            }
        }
    }
    Go
  • 相关阅读:
    jfixed使固定行列可编辑表格
    Base 64 加密、解密
    去除富文本格式
    阿里移动安全挑战赛第二题研究小结
    CyanogenMod源码下载、编译、刷机过程记录(HTC buzz)
    编译民间安卓源码mokesoures4.2.2报错内容【解决了!】
    Linux下通过NDK的初步使用【详细步骤+截图】
    Linux下实现JNI期间发生的错误……【未解决】
    C++调用Java方法时jvm.dll相关错误 【每次记录完后都被瞬间解决了……】
    JNI学习中——JVM错误:EXCEPTION_ACCESS_VIOLATION (0xc0000005)
  • 原文地址:https://www.cnblogs.com/Pneuis/p/15164226.html
Copyright © 2020-2023  润新知