weekly_contest_271_leetcode2106. 摘水果

10 篇文章 0 订阅
4 篇文章 0 订阅

在一个无限的 x 坐标轴上,有许多水果分布在其中某些位置。给你一个二维整数数组 fruits ,其中 fruits[i] = [positioni, amounti] 表示共有 amounti 个水果放置在 positioni 上。fruits 已经按 positioni 升序排列 ,每个 positioni 互不相同 。

另给你两个整数 startPos 和 k 。最初,你位于 startPos 。从任何位置,你可以选择 向左或者向右 走。在 x 轴上每移动 一个单位 ,就记作 一步 。你总共可以走 最多 k 步。你每达到一个位置,都会摘掉全部的水果,水果也将从该位置消失(不会再生)。

返回你可以摘到水果的 最大总数 。

示例 1:

输入:fruits = [[2,8],[6,3],[8,6]], startPos = 5, k = 4
输出:9
解释:
最佳路线为:

  • 向右移动到位置 6 ,摘到 3 个水果
  • 向右移动到位置 8 ,摘到 6 个水果
    移动 3 步,共摘到 3 + 6 = 9 个水果
    示例 2:

输入:fruits = [[0,9],[4,1],[5,7],[6,2],[7,4],[10,9]], startPos = 5, k = 4
输出:14
解释:
可以移动最多 k = 4 步,所以无法到达位置 0 和位置 10 。
最佳路线为:

  • 在初始位置 5 ,摘到 7 个水果
  • 向左移动到位置 4 ,摘到 1 个水果
  • 向右移动到位置 6 ,摘到 2 个水果
  • 向右移动到位置 7 ,摘到 4 个水果
    移动 1 + 3 = 4 步,共摘到 7 + 1 + 2 + 4 = 14 个水果
    示例 3:

输入:fruits = [[0,3],[6,4],[8,5]], startPos = 3, k = 2
输出:0
解释:
最多可以移动 k = 2 步,无法到达任一有水果的地方

提示:

1 <= fruits.length <= 105
fruits[i].length == 2
0 <= startPos, positioni <= 2 * 105
对于任意 i > 0 ,positioni-1 < positioni 均成立(下标从 0 开始计数)
1 <= amounti <= 104
0 <= k <= 2 * 105

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-fruits-harvested-after-at-most-k-steps
过后发现有好多大佬有好多种做法,比如有大佬用优先队列做的膜拜膜拜!。蒻鸡现场只想到了一种基于二分的做法,预处理出前缀和,二分答案:然后check:枚举单侧取的个数,本侧距离乘1 另一侧乘2,分别判断两侧。直到搜到结果,复杂度O(NlogNlogN)
代码贼长自己看 耗时上天了鸭。

const int N = 1e5+100;

struct node{
		int p;
		int nm;
		node(int a,int b){
            p=a;nm=b;
        }
        bool operator <(const int t) const{
			return nm<t;
		}
		bool operator ==(const int t) const{
			return nm==t;
		}
		bool operator >(const int t) const{
			return (!(nm==t))&&(!(nm<t));
		}
	};
class Solution {
	
	vector<node> ay;
	vector<node> by;
	int n;
	bool check1(int md,int k){
		auto p = lower_bound(ay.begin(),ay.end(),md);
		if(p==ay.end()) p--;
		while(p>=ay.begin()){
			int eps = md-p->nm;
			if(eps>0){
				auto q = lower_bound(by.begin(),by.end(),eps);
				if(q==by.end()) return false;
				if(p->p+2*(q->p)<=k) return true;
			}
			else{
				if(p->p<=k) return true;
			}
			p--;
		}
        return false;
	}
	bool check2(int md,int k){
		auto p = lower_bound(by.begin(),by.end(),md);
		if(p==by.end()) p--;
		while(p>=by.begin()){
			int eps = md-p->nm;
			if(eps>0){
				auto q = lower_bound(ay.begin(),ay.end(),eps);
				if(q==ay.end()) return false;
				if(p->p+2*(q->p)<=k) return true;
			}
			else{
				if(p->p<=k) return true;
			}
			p--;
		}
        return false;
	}
public:
    int maxTotalFruits(vector<vector<int>>& a, int st, int k) {
		int res=0;
		int l=0,r=20;n=a.size();
		ay.clear(); by.clear();
		by.push_back(node(0,0));
		for(auto t:a){
			if(t[0]<st){
				ay.push_back(node(st-t[0],t[1]));
				r+=t[1];
			}
			else if(t[0]>st){
				by.push_back(node(t[0]-st,t[1]));
				r+=t[1];
			}
			else{
				res=t[1];
			}
		}
		ay.push_back(node(0,0));
		reverse(ay.begin(),ay.end());
		for(int i=1;i<ay.size();i++){
			ay[i].nm=ay[i-1].nm+ay[i].nm;
		}
		for(int i=1;i<by.size();i++){
			by[i].nm=by[i-1].nm+by[i].nm;
		}
		while (l < r)
		{
			int mid = l + r + 1 >> 1;
			if (check1(mid,k)||check2(mid,k)) l = mid;
			else r = mid - 1;
		}
		return l+res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值