• P1868 饥饿的奶牛


    P1868 饥饿的奶牛

    原题链接:传送门

    分析

    首先根据数据范围可知此问题的时间复杂度大概限制(O(n) / O(nlong_n)) 左右。由于是问的最多往贪心/dp方向思考

    题目中指出可以选择任意区间但是这些区间不能有重叠的部分

    对于一个区间[l, r],一共有两种可能

    我们假设(f(i)) 表示前 i 个区间可以获取的最大价值

    • 选择这个区间

      如果我们要选择第 i 个区间,那么我们需要前 i - 1 个区间可以获取的最大价值

      (f(i) = f(k) + r - l + 1 (k 为上一个紧接着的区间))

    • 不选择这个区间

      (f(i) = f(i-1))

    那么问题的关键就在于如何找到第一种情况中的 k 的下标。我们可以根据区间的 r 值对这个所有区间进行一次排序操作。

    对于每一个区间([l,r]),我们只需要找到最后一个 k < r 的区间的下标

    这个问题是一个线性dp问题其中串联使用了二分来搜索状态
    从状态的定义到状态的寻找,从dp-->二分环环相扣。
    

    AC 代码

    C++ code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 200005;
    
    typedef long long ll;
    
    struct node{
    	int l, r;
    }e[N];
    
    ll f[N], n;
    
    
    bool cmp(node a,node b)
    {
    	return a.r < b.r;
    }
    
    int main()
    {
    	cin >> n;
    
    	for(int i = 1; i <= n; i ++)
    	{
    		cin >> e[i].l >> e[i].r;
    	}
    
    	sort(e + 1, e + 1 + n, cmp);
    
    	for(int i = 1; i <= n; i ++)
    	{
    		ll w = e[i].r - e[i].l + 1;
    		f[i] = w;
    		int l = 1, r = i - 1;
    		while(l < r)
    		{
    			int mid = l + r + 1 >> 1;
    			if(e[mid].r < e[i].l)l = mid;
    			else r = mid - 1;
    		}
    		if(e[l].r < e[i].l)
    		{
    			f[i] = max(f[i-1], f[i] + f[l]);
    		} else {
    			f[i] = max(f[i], f[i-1]);	
    		}
    	}
    	cout << f[n] << endl;
    	return 0;
    }
    
  • 相关阅读:
    MAVEN 安装与配置
    MAVEN 常用仓库地址
    一些常用的工具
    springFramework 源码学习之源码下载与编译
    测试工程师学习笔记
    什么是多态
    聚簇索引与非聚簇索引
    正则表达式菜鸟教程
    我的第一篇博客
    转Hibernate继承
  • 原文地址:https://www.cnblogs.com/wlw-x/p/14724923.html
Copyright © 2020-2023  润新知