zoukankan      html  css  js  c++  java
  • [LeetCode] 1052. Grumpy Bookstore Owner 暴躁的书店老板


    Today, the bookstore owner has a store open for customers.length minutes.  Every minute, some number of customers (customers[i]) enter the store, and all those customers leave after the end of that minute.

    On some minutes, the bookstore owner is grumpy.  If the bookstore owner is grumpy on the i-th minute, grumpy[i] = 1, otherwise grumpy[i] = 0.  When the bookstore owner is grumpy, the customers of that minute are not satisfied, otherwise they are satisfied.

    The bookstore owner knows a secret technique to keep themselves not grumpy for X minutes straight, but can only use it once.

    Return the maximum number of customers that can be satisfied throughout the day.

    Example 1:

    Input: customers = [1,0,1,2,1,1,7,5], grumpy = [0,1,0,1,0,1,0,1], X = 3
    Output: 16
    Explanation: The bookstore owner keeps themselves not grumpy for the last 3 minutes.
    The maximum number of customers that can be satisfied = 1 + 1 + 1 + 1 + 7 + 5 = 16.
    

    Note:

    • 1 <= X <= customers.length == grumpy.length <= 20000
    • 0 <= customers[i] <= 1000
    • 0 <= grumpy[i] <= 1

    这道题说是有个脾气暴躁的书店老板,一个月总有那么几天暴躁,他一暴躁,顾客的满意度就直线下降。现在给了一个数组 grumpy,说是这个店主在若干分钟内不定时的就会暴躁,对应的时间内书店的客人数量保存在 customers 数组中。但老板有个神奇的方法可以使得自己在连续的X分钟内不暴躁,需要合理使用才能使得更多的顾客满意,让返回最大的满意的顾客数量。首先来想,若这个更年期老板没有这个神奇的方法(太太乐口服液?),那么暴躁的时间就是固定的,则不暴躁时能满足的客人的数量也是确定的,这个可以提前求出来。而使用了神奇配方之后,可以连续X分钟不暴躁,这段时间内原本就不暴躁的区间不会受到影响,即满意的顾客数不会增加。只有这段时间内原本暴躁的分钟内,变的不暴躁了,才会增加满意顾客的数量。为了快速的知道X时间段内暴躁时段的顾客人数,需要建立一个累加数组,只统计暴躁时间段的顾客人数,放到数组 ones 中。同时用一个变量 sum 来统计所有不暴躁时间段的顾客人数,最后只要遍历每个大小为X的窗口,利用 ones 数组来快速得到暴躁时间段的顾客人数,并且加上 sum,用来更新结果 res 即可,参见代码如下:


    解法一:

    class Solution {
    public:
        int maxSatisfied(vector<int>& customers, vector<int>& grumpy, int X) {
            int n = customers.size(), res = 0, sum = 0;
            vector<int> ones(n + 1);
            for (int i = 1; i <= n; ++i) {
                ones[i] += ones[i - 1];
                if (grumpy[i - 1] == 1) {
                    ones[i] += customers[i - 1];
                } else {
                    sum += customers[i - 1];
                }
            }        
            for (int i = 0; i + X <= n; ++i) {
                res = max(res, sum + ones[i + X] - ones[i]);
            }
            return res;
        }
    };
    

    我们还可以写的更加简洁一下,只用一个 for 循环,这里的 sums 数组就相当于上面的 ones 数组,然后直接把不暴躁时间段的顾客人数加到结果 res 中。在累加 sums 数组的过程中,用当前最后的那个X大小的窗口来更新 mx,最后将 mx 加到结果 res 中并返回即可,参见代码如下:


    解法二:

    class Solution {
    public:
        int maxSatisfied(vector<int>& customers, vector<int>& grumpy, int X) {
            int res = 0, n = customers.size(), mx = 0;
            vector<int> sums(n + 1);
            for (int i = 0; i < n; ++i) {
                sums[i + 1] = sums[i];
                if (grumpy[i] == 0) res += customers[i];
                else sums[i + 1] += customers[i];
                if (i + 1 - X >= 0) mx = max(mx, sums[i + 1] - sums[i + 1 - X]);
            }
            return res + mx;
        }
    };
    

    Github 同步地址:

    https://github.com/grandyang/leetcode/issues/1052


    参考资料:

    https://leetcode.com/problems/grumpy-bookstore-owner/

    https://leetcode.com/problems/grumpy-bookstore-owner/discuss/299237/C%2B%2B-Sliding-Window

    https://leetcode.com/problems/grumpy-bookstore-owner/discuss/299230/JavaPython-3-Sliding-window.


    LeetCode All in One 题目讲解汇总(持续更新中...)

  • 相关阅读:
    【POJ3237】Tree 树链剖分+线段树
    【BZOJ3531】[Sdoi2014]旅行 树链剖分+动态开点线段树
    【BZOJ4034】[HAOI2015]树上操作 树链剖分+线段树
    【BZOJ1984】月下“毛景树” 树链剖分+线段树
    【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
    【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分
    树形DP水题杂记
    【BZOJ1827】[Usaco2010 Mar]gather 奶牛大集会 树形DP
    【BZOJ1864】[Zjoi2006]三色二叉树 树形DP
    【BZOJ1060】[ZJOI2007]时态同步 树形DP
  • 原文地址:https://www.cnblogs.com/grandyang/p/14506747.html
Copyright © 2011-2022 走看看