洛谷P1868 饥饿的奶牛

一,题目

# 饥饿的奶牛

## 题目描述

有一条奶牛冲出了围栏,来到了一处圣地(对于奶牛来说),上面用牛语写着一段文字。

现用汉语翻译为:

有 $N$ 个区间,每个区间 $x,y$ 表示提供的 $x\sim y$ 共 $y-x+1$ 堆优质牧草。你可以选择任意区间但不能有重复的部分。

对于奶牛来说,自然是吃的越多越好,然而奶牛智商有限,现在请你帮助他。

## 输入格式

第一行一个整数 $N$。

接下来 $N$ 行,每行两个数 $x,y$,描述一个区间。

## 输出格式

输出最多能吃到的牧草堆数。

## 样例 #1

### 样例输入 #1

```
3
1 3
7 8
3 4
```

### 样例输出 #1

```
5
```

## 提示

$1 \leq n \leq 1.5 \times 10^5$,$0 \leq x \leq y \leq 3 \times 10^6$。

链接:https://www.luogu.com.cn/problem/P1868

二,思路

先根据y值从小到大排序,再用动态规划来做,dp[i]代表前i个区间吃到的最多的牧草数,dp[i]可以从dp[i-1]转移,即不取第i个区间得到的牧草数,也可以从前面的dp来转移,即不取第i个区间得到的牧草数,从二者取最大值。

注,由于数据量过大,从前面的dp转移的算法需要优化,此时我们发现,如果当有一段区间的y刚好小于第i个区间的x,该dp和该区间前面的dp满足转移的条件,而后面的则会不满足,而该dp是前面所有dp的最优值,所以,只需要找到该dp所在的位置即可,所以可以用二分查找。

三,代码

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <cmath>
#include <deque>
#include <algorithm>
#include <vector>
using namespace std;
struct node
{
	int x, y;
};
bool cmp(node n1, node n2)
{
	return n1.y < n2.y;
}
signed main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int N;
	cin >> N;
	deque<node> d(N + 1);
	for (int i = 1; i <= N; ++i) cin >> d[i].x >> d[i].y;
	sort(d.begin(), d.end(), cmp);
	vector<int> dp(N + 1);
	for (int i = 1; i <= N; ++i)
	{
		int l = 0, r = i;
		while (l < r)
		{
			int mid = (l + r + 1) >> 1;
			if (d[mid].y < d[i].x) l = mid;
			else r = mid - 1;
		}
		dp[i] = max(dp[l] + d[i].y - d[i].x + 1, dp[i - 1]);
	}
	cout << dp[N];
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值