• poj1769 线段树优化的dp


      附上这道题的链接:http://poj.org/problem?id=1769

      题目的意思是有一个装置可以输出n个数的最大值, 这个装置由m个排序器组成, 每个排序器可以将这n个数从s 到 t的数按照从小到大的顺序排列, 有一个人发现将m个排序器中的一些排序器去掉仍然不影响功能,  现在问你最少需要多少个排序器可以完成功能。 我们可以定义dp[i][j]为前i个排序器将第1个数提到j所需要的最少的排序器的数量, 那么当t[i] == j的时候 dp[i][j] = min(dp[i-1][j] , min(dp[i-1][si -- ti]) + 1)  当ti != j的时候 dp[i][j] = dp[i-1][j],  我们观察状态数有m*n个, 显然直接求解会超时, 因此我们考虑使用线段树来优化  见挑战程序设计 p207 , 代码如下:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    const int maxn = 500000 + 100;
    const int inf = 0x3f3f3f3f;
    int n, m;
    
    struct segment{
        int l, r;
        int x;
    }seg[3*maxn];
    
    void build(int rt, int l, int r) {
        seg[rt].l = l; seg[rt].r = r;
        if(l == r) {
            int value = inf;
            if(l == 1) value = 0;
            seg[rt].x = value;
            return ;
        }
        int chl = 2*rt, chr = 2*rt + 1;
        int mid = (l + r) / 2;
        build(chl, l, mid);
        build(chr, mid+1, r);
        seg[rt].x = min(seg[chl].x, seg[chr].x);
    }
    
    int query(int rt, int l, int r) {
        if(seg[rt].l == l && seg[rt].r == r) {
            return seg[rt].x;
        }
        int mid = (seg[rt].l + seg[rt].r)/2;
        if(r <= mid)
            return query(2*rt, l, r);
        else if(l > mid)
            return query(2*rt+1, l, r);
        else{
            int v1 = query(2*rt, l, mid);
            int v2 = query(2*rt+1, mid+1, r);
            return min(v1, v2);
        }
    }
    
    void update(int rt, int i, int c) {
        if(seg[rt].l==seg[rt].r && seg[rt].l == i) {
            seg[rt].x = c;
            return ;
        }
        int mid = (seg[rt].l + seg[rt].r)/2;
        if(i <= mid)
            update(2*rt, i, c);
        else
            update(2*rt+1, i, c);
        seg[rt].x = min(seg[2*rt].x, seg[2*rt+1].x);
    }
    
    int main() {
        while(scanf("%d%d", &n, &m) != EOF) {
            build(1, 1, n);
            for(int i=0; i<m; i++) {
                int s, t;
                scanf("%d%d", &s, &t);
                int v1 = query(1, s, t) + 1;
                int v2 = query(1, t, t);
                int v3 = min(v1, v2);
                update(1, t, v3);
            }
            printf("%d
    ", query(1, n, n));
        }
        return 0;
    }
  • 相关阅读:
    【Web】JavaScript 语法入门
    tar 和gzip 的区别
    状态码,好记
    PyCharm与git/GitHub取消关联
    在Ubuntu下安装deb包需要使用dpkg命令
    linux每日命令(4):解压命令
    Python之os.path.join()
    Python的JAVA胶水——jpype
    python之chardet验证编码格式
    python之arrow时间处理模块
  • 原文地址:https://www.cnblogs.com/xingxing1024/p/5487428.html
Copyright © 2020-2023  润新知