商店
题目大意
题目描述
一条街上有 n 个商店,在第 i 个商店,可以以 a i a_i ai 的价格买入一个商品,也可以以 a i a_i ai 的价格卖出一个商品。商品很沉,最多只能同时拿着 1 个商品在街上走。现在按照给定顺序依次访问所有商店,那么,最大收益是多少?在获得最大收益的前提下,最少交易次数是多少?
输入格式
第一行一个整数 T (1≤T≤5),代表测试用例个数
下面 T 组数据,其中每一组数据都占两行,其中
第一行一个整数 n (1≤n≤105),代表商店个数
下面一行 n 个整数,其中第 i 个数为 *
a
i
a_i
ai (0≤
a
i
a_i
ai*<2147483648),代表在第 i 个商店可以买入或卖出商品的价格
输出格式
对于每个例子,输出一行两个整数,分别代表最大收益和获得最大收益的前提下最少的交易次数
测试样例
输入:
1
5
9 10 7 6 8
输出:
3 4
解法
首先使用贪心算法,一家一家商铺看,如果后一家商铺的 a i a_i ai 大于当前这家,则就将商品在当前这家买入并在后一家卖出,否则就不在当前这家商铺购买商品。通过该策略可确定最大收益。
设置变量 maichu 用来记录上一次卖出
商品的商铺,当下一次购买时就判断买入
的商铺下标是否和上一次相同,若相同,就不再
增加交易次数,否则交易次数增加 2 (因为买入一次,卖出一次)。
时间复杂度
O ( T n ) O(Tn) O(Tn)
最外层输入测试用例的时间复杂度为 O ( T ) O(T) O(T) ;输入各个商铺的 a i a_i ai 的时间复杂度为 O ( n ) O(n) O(n) ;判断是否进行交易的循环中时间复杂度为 O ( n ) O(n) O(n) 。综上,时间复杂度为 O ( T n ) O(Tn) O(Tn) 。
代码
#include <bits/stdc++.h>
using namespace std;
long long a[1000000] = {0}; //记录商品价格
// 0 1 1 2 3
int main()
//一天天看,如果后一项小于前一项就不买,也不可能存在后一项小于前一项的时候买前一项会赚,因为直接买后一项赚更多
{
int T;
scanf("%d", &T);
for (int i = 1; i <= T; i++)
{
long long n;
scanf("%lld", &n);
for (long long j = 0; j < n; j++)
{
scanf("%lld", &a[j]);
}
long long W = 0; //记录收益
long long time1 = 0; //记录交易次数
long long maichu = -1; //记录上一次卖出商品的商铺
for (long long j = 0; j < n - 1; j++)
{
if (a[j] < a[j + 1]) //若满足后一天价格比今天高,就买入
{
W += (a[j + 1] - a[j]);
if (j != maichu) //计算最少交易次数,当当前交易买入与前一天的卖出相同就可以省略
{
time1 += 2;
}
maichu = j + 1;
}
else if (a[j] == a[j + 1]) //假交易,当价格相同的时候又遇到前一天买进,则也要假装买进然后明天卖出,因为为了保证最少交易次数,要是遇到价格相同好几天又最后升价了,就要一直假交易买进卖出直到后一天价格比前一天低(即亏本)或是到了最后一天
{ //即我昨天买进又遇到今明两天价格相同,那么今天就要假交易
if (j == maichu)
{
maichu = j + 1;
}
}
}
cout << W << ' ' << time1 << endl;
}
return 0;
}