贪心-牛客-买卖赚钱最多

问题链接

问题:

给出一个物品在n个商店的不同价值,从第一个商店走到第n个商店

可以选择花钱买这个物品,也可以选择卖这个物品,但是身上只能带一个

问最后最多赚多少

输入

1.  T组数据,

2 . n个商店, <  100000

3.  在n个商店的价值 v, v < int

输出

两个数,赚的钱 和 最少交易的次数

输入

1
5
9 10 7 6 8

输出

3 4

分析:

1. 如果 价值 是递增的, 那么,最后的 赚钱的最大值,一定是 a[ n ] - a[ 1 ] (假设所有的价值从a[1] 存到 a[ n ] )

   因为只能带一个商品,那么第一次买入,一定选择最小的 a [ 1 ] , 最后一次卖出一定是最大的 a[ n ]!!!

  中间不管怎么交易都会小于或等于这个值。。比如   ,a  b   c   d (a < b < c < d)a 买 ,b卖,c买,d卖

   ans = ( b - a) + (d - c) =  ( d - a ) - ( c - d )...(c - d) > 0..

   但是 如果 (a买 b卖)(  b买   c卖)(c买  d卖)  这样

    ans  = (b - a)+(c - b)+( d - c ) = d - a ....

     也就是说 赚没相邻两个商店的差价,最后的和就是最大赚钱值

2. 如果价值不是递增的。

    那肯定是由许多个  递增的 小子序列 组成 

    把每一个递增的小子序列按 1  的思路求得ans  最后所有的ans相加

    a  b   c   d  (  b > a,  c <=  b,  d > c , d > b) ---( 1  3  2  5 )

   ans1 = d-a

   ans2 = (b-a) + (d - c) = (d - a) + ( b - c ) .....( b - c) >= 0 ...所以ans2 是最优解

总结:

对于一个数列,只要相邻的两个价值可以赚钱,那就 ans += (a[  n + 1]  -  a[ n ])...

至于最少的交易次数。。。。。。

可以每一个商店做一个标记,每交易一次标记就 ++,也就是买入,标记++,卖出 ,标记++

那么标记最大值是 2  最小值是 0,

那么最后只把标记值是 1 的算上次数,也就是实际只在标记值是 1 ,的商店买入 或者  卖出。。。

但是这样有一个 bug。。。。。

比如:1  2  2  3. 应该是交易2次,但是按以上的算法是交易 4 次。

因为 2 2 的标记都是 1 , 但其实2 2 是不需要交易的。

也就是说,有相邻的数字是重复的话,会出现bug。。。

解决的方法很简单。。。只要在 输入的时候把相邻的重复筛掉,只留下一个,就ok了

并不影响结果。

   

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
 
using namespace std;
 
typedef long long LL;
 
const int MAXN = 1e5+5;
 
struct Node
{
    LL id;
    LL v;
}a[MAXN];
 
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        LL n;
        LL sum = 0;
        LL cnt = 0;
        memset(a,0,sizeof(a));
        scanf("%lld",&n);
        for (int i = 0; i < n; i++)
        {
            a[i].id = 0;
            LL x;
            scanf("%lld",&x);
            if (x == a[i-1].v)
            {
                i--;
                n--;
                continue;
            }
            else
            {
                a[i].v = x;
            }
        }

        for (int i = 0; i < n; i++)
        {
  
            if (a[i].v < a[i+1].v)
            {
                sum += a[i+1].v - a[i].v;
                a[i].id ++;
                a[i+1].id ++;
            }
        }
 
        for (int i = 0; i < n; i++)
        {
            if (a[i].id == 1)
                cnt ++;
        }
        cout << sum << " " << cnt <<endl;
    }
 
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41003528/article/details/81174731
今日推荐