题解 洛谷 P4873 [USACO14DEC] Cow Jog_Gold 牛慢跑(金)

洛 谷   P 4873   [ U S A C O 14 D E C ] C o w J o g G o l d 牛 慢 跑 ( 金 ) \color{#00F}{洛谷\ P4873\ [USACO14DEC] Cow Jog_Gold 牛慢跑(金)}  P4873 [USACO14DEC]CowJogGold()
T i m e L i m i t : 1000 M S \color{green}{Time Limit: 1000 MS} TimeLimit:1000MS
M e m o r y L i m i t : 125.00 M B \color{green}{Memory Limit: 125.00MB} MemoryLimit:125.00MB

P r o b l e m   D e s c r i p t i o n \color{blue}{Problem\ Description} Problem Description
Farmer John 的 N N N 头奶牛 ( 1 ≤ N ≤ 1 0 5 ) (1 ≤ N ≤ 10^5) (1N105)正在一条长度无限的跑道上慢跑,每头奶牛都有一个不同的开始位置,以及不同的跑步速度。

为了方便奶牛们互相超越,整个跑道被分成了若干条赛道。在同一时刻,不可能有在同一条赛道上的两头奶牛占据相同的位置。

现在奶牛们要跑 T T T分钟,在跑步过程中,他们不会改变自己所在的赛道和自己跑步的速度。FJ想要知道,为了奶牛间不会发生冲突,他需要至少准备多少条赛道。

I n p u t \color{blue}{Input} Input
第一行包括两个整数 N N N T T T 。接下来 N N N 行,每行两个整数 p i p_i pi v i ( p i , v i ≤ 1 0 9 ) v_i( p_i , v_i ≤ 10^9 ) vi(pi,vi109),分别代表奶牛的初始位置和速度。

O u t p u t \color{blue}{Output} Output
一个整数,代表最少需要的跑道数目。

S a m p l e   I n p u t \color{blue}{Sample\ Input} Sample Input
5 3
0 1
1 2
2 3
3 2
6 1

S a m p l e   O u t p u t \color{blue}{Sample \ Output} Sample Output
3


对于两头牛, A A A牛和 B B B牛,如果 A A A牛超过了 B B B牛,则说明 A A A牛初始位置   ⩽ B \ \leqslant B  B牛初始位置且 A A A牛结束位置   ⩾ B \ \geqslant B  B牛结束位置。在这种情况下,它们需要两条跑道。

同样的,如果有 k k k头牛,第一头牛超过第二头牛,第二头牛超过第三头牛……,则说明它们的初始位置是不下降的,结束位置是不上升的。在这种情况下,它们需要 k k k条跑道。

对于 n n n头牛,问它们最少需要多少跑道,其实就是能满足初始位置不下降,结束位置不上升最多能选出多少头牛。由于输入以按照升序,所以我们只要考虑结束位置就行。即求结束位置的最长不上升子序列。

代码实现如下:

#include <bits/stdc++.h>
#define ll long long 
using namespace std;

const int MAXN=100000+10;
int n,t,top=0;
ll a[MAXN],q[MAXN];

inline ll read()
{
	ll X=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();}
	while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+(ch^'0'); ch=getchar();}
	return X*f;
}

int main()
{
	//freopen("input.txt","r",stdin);
	n=read(); t=read();
	for(int i=1;i<=n;++i)
	{
		ll p=read(),v=read();
		a[i]=(ll)p+v*t;
	}
	for(int i=n;i>=1;--i)//倒过来变成求最长不下降子序列 
	{
		if(!top||a[i]>=q[top])
			q[++top]=a[i];
		else 
		{
			ll pos=upper_bound(q+1,q+top+1,a[i])-q;
			q[pos]=a[i];
		}
	}
	printf("%lld",top);
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值