• POJ1769(线段树+DP)


    飞翔

    题意 : 给定一个区间长度 n ,接下来给出 m 个子区间,要求最少选出多少个区间才能使得 1~n 这个区间被所选的所有子区间覆盖

    分析:

    首先是动态规划,dp[i]表示把最大值从1位置搞到第i个小装置结尾最少需要多少个小装置,这样的话,从小到大遍历所有装置,每次查询当前装置之前的装置区间和当前装置相交的装置,更新dp就可以了。

    那么问题就来了,装置有m个,这样O(m^2)的算法绝壁TLE。

    用线段树来维护区间最小dp值信息,每个点维护ll到rr范围内的dp最小是多少。没算完一个新的小装置只需把它的dp值插到树上就行了。

    然后TLE了,这里有个小贪心,每次更新不需要更新区间信息,因为对每个区间,r点之前的信息对更新之后的装置dp没有贡献,因为要努力使最大值向右移,因此单点更新即可。

    AC代码:

    #include <cstdio>
    #include <algorithm>
    #include <string.h>
    using namespace std;
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    const int maxn = 5e4 + 10;
    const int INF = 0x3f3f3f3f;
    int minx[maxn<<2];
    int dp[maxn];
    int L[500010], R[500010];
    
    void PushUP(int rt) { minx[rt] = min(minx[rt<<1], minx[rt<<1|1]); }
    void build(int l,int r,int rt) {
        if (l == r) {
            minx[rt] = INF;
            return ;
        }
        int m = (l+r)>>1;
        build(lson);
        build(rson);
        PushUP(rt);
    }
    void update(int p,int sc,int l,int r,int rt) {//单点更新,参数(更新点,更新值,总区间左端点,总区间右端点,根节点编号)
        if (l == r) {
            minx[rt] = sc;
            return ;
        }
        int m =(l+r)>>1;
        if (p <= m) update(p , sc , lson);
        else update(p , sc , rson);
        PushUP(rt);
    }
     int query(int L,int R,int l,int r,int rt) {//查询最大值的写法、最小值同理、求和区间写法在下面
         if (L <= l && r <= R)
             return minx[rt];
    
         int m = (l + r) >> 1;
         int ret = INF;
         if (L <= m) ret = min(ret , query(L , R , lson));
         if (R > m) ret = min(ret , query(L , R , rson));
         return ret;
     }
    
    int main(void)
    {
        int m, n;
        scanf("%d %d", &n, &m);
            for(int i=1; i<=m; i++)
                scanf("%d %d", &L[i], &R[i]);
            build(1, n, 1);
            for(int i=1; i<=n; i++)
                dp[i] = INF;
            dp[1] = 0;
            update(1, 0, 1, n, 1);
            for(int i=1; i<=m; i++){
                int val = query(L[i], R[i], 1, n, 1) + 1;
                if(val < dp[R[i]]){
                    //printf("%d %d
    ", L[i], R[i]);
                    update(R[i], val, 1, n, 1);
                    dp[R[i]] = val;
                }
            }
            printf("%d
    ", dp[n]);
    
        return 0;
    }
    View Code
  • 相关阅读:
    数据结构与算法-基础(七)完全二叉树
    数据结构与算法-基础(六)二叉树基础
    数据结构与算法-基础(五)队列(Qeque)
    数据结构与算法-基础(四)栈(Stack)
    数据结构与算法-基础(三)- 循环链表(补充)
    数据结构与算法-基础(二)单向链表
    数据结构与算法-基础(一)动态数组
    Swift-Button 的 highlighted(高亮)
    Android现有工程使用Compose
    Android Jetpack Compose 引入示例工程
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/9102836.html
Copyright © 2020-2023  润新知