zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    【leetcode】1365. How Many Numbers Are Smaller Than the Current Number
    【leetcode】1363. Largest Multiple of Three
    【leetcode】1362. Closest Divisors
    【leetcode】1361. Validate Binary Tree Nodes
    【leetcode】1360. Number of Days Between Two Dates
    【leetcode】1359. Count All Valid Pickup and Delivery Options
    【leetcode】1357. Apply Discount Every n Orders
    【leetcode】1356. Sort Integers by The Number of 1 Bits
    ISE应用入门的一些问题
    DDR的型号问题
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/9102836.html
Copyright © 2011-2022 走看看