列表

详情


NC230371. 生蚝接柿子

描述

这天,生蚝来到了柿子园,想采一些柿子送给妹妹们。但是柿子树太高了,生蚝根本摘不到。正在他苦恼的时候,突然刮起了一阵大风,天上就像下起了柿子雨。柿子掉到地上就会摔坏,于是生蚝赶紧去接,站在一旁看热闹的zech向你提出了一个问题:生蚝最多可以接到多少个柿子呢?

已知所有柿子都在一条与水平面平行的直线上,我们以这条直线为x轴,垂直于水平面方向为y轴建立坐标系,zech发现这些柿子的x坐标和y坐标都是正整数,且所有柿子的y坐标互不相同,已知生蚝张开双臂后两手掌间的距离是len-1,落在两手掌间的柿子都能被接到(包括两手掌),一开始生蚝张开双臂后最左端坐标是(x_0,0)x_0为正整数,生蚝的最快移动速度为,每个柿子的下落速度都是,即1s后原本在(x,y)的柿子会掉到(x,y-1)位置,若柿子掉到的位置时不在生蚝的双手范围内则柿子会摔碎,否则生蚝将接到这个柿子。那么最终生蚝能接到最多多少个柿子呢?

输入描述

第一行四个正整数n,v,x_0,len
第二行到第行每行两个正整数x,y,表示柿子的位置,保证y互不相同。

输出描述

一行,一个非负整数,表示生蚝能接到的柿子的最大个数。

示例1

输入:

5 1 5 1
2 10
1 3
1 9
4 2
3 7

输出:

4

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++ 11.0.1) 解法, 执行用时: 108ms, 内存消耗: 604K, 提交时间: 2022-11-06 21:27:25

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 3e3 + 9;
int n, v, x0, len, L = 3e3;
int f[maxn], g[maxn];

struct Point
{
	int x, y;
}p[maxn];

void work(int m)//
{
	memcpy(g, f, sizeof f);//f -> g, g = the last f
	memset(f, 0xcf, sizeof f);//f = 0
	
	deque<int> dq;//队列存放的是下标 
	for(int i = 1, j = 1;i <= L; ++ i)//枚举左端点, 维护[i - m, i + m]最大值 
	{
		while(j <= L && j <= i + m)
		{
			//调整位置,将队尾小的弹出 
			while(!dq.empty() && g[j] >= g[dq.back()])dq.pop_back();
			dq.push_back(j ++);
		}
		
		//将不符合要求的队头弹出,如果下标不在[i - m, i + m]就不符合要求 
		while(!dq.empty() && dq.front() < i - m)dq.pop_front();
		
		//队头维护的是[i, i + m]最大值,也就是f[i]和f[i + m]的新值 
		f[i] = g[dq.front()];
	}
	
}

signed main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> n >> v >> x0 >> len;
	
	for(int i = 1;i <= n; ++ i)cin >> p[i].x >> p[i].y;
	
	sort(p + 1,p + 1 + n, [](const Point &a, const Point &b)
	{
		return a.y < b.y;
	});
	memset(f, 0xcf, sizeof f);
	f[x0] = 0;
	
	int la = 0;
	for(int i = 1;i <= n; ++ i)
	{
		work((p[i].y - la) * v);
		//状态转移 
		for(int j = 1;j <= L; ++ j)
			if(j <= p[i].x && p[i].x <= j + len - 1)f[j] ++;
			
		la = p[i]. y;
	}
	
	
	int ans = 0;
	for(int i = 1;i <= L; ++ i)ans = max(ans, f[i]);
	cout << ans << '\n';
	return 0;
}

C++(g++ 7.5.0) 解法, 执行用时: 76ms, 内存消耗: 592K, 提交时间: 2022-11-20 11:49:25

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x7f7f7f7f;
struct node
{
    int x,y;
    bool operator< (const node &b) const {return y < b.y;}
}ar[3005];
int dp[3005],f[3005];
int que[3005];
int n,v,x0,len;
void getmax(int m)
{
    for(int i=1;i<=3000;i++)
        f[i] = dp[i];
    int head = 1,tail = 0;
    for(int i=1,j = 1;i<=3000;i++)
    {
        while(j <= min(3000,i+m))
        {
            while(head <= tail && f[que[tail]] <= f[j])
                tail--;
            que[++tail] = j++;
        }
        while(que[head] < i - m) head++;
        dp[i] = f[que[head]];
    }
}
void solve()
{
    scanf("%d%d%d%d",&n,&v,&x0,&len);
    for(int i=1;i<=n;i++)
    {
        scanf("%d %d",&ar[i].x,&ar[i].y);
        f[i] = dp[i] = -INF;
    }
    dp[x0] = 0;
    sort(ar+1,ar+n+1);
    for(int i=1;i<=n;i++)
    {
        int r = (ar[i].y - ar[i-1].y) * v;
        getmax(r);
        for(int j=1;j<=3000;j++)
            if (j <=ar[i].x && j+len-1 >= ar[i].x)
                dp[j]++;
    }
    int ans = 0;
    for(int i=1;i<=3000;i++)
        ans = max(ans,dp[i]);
    printf("%d\n",ans);
    
}

int main()
{
    solve();
}

上一题