zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    怎样简单编写一个html网页
    C# 委托实现冒泡排序
    C# 运算符
    EF 多表联查方法
    Log4net 配置文件
    vs调试 iis发布之后的项目
    继承 ,构造方法使用
    C#扩展方法
    partial 部分类
    WeakReference 弱引用
  • 原文地址:https://www.cnblogs.com/wlw-x/p/14724923.html
Copyright © 2011-2022 走看看