小测试 炒书

题目背景: 
作为一名成功人士,kk 也想大捞一笔,于是他选择了一种最好的方式——写书。 果不其然,kk 的书在投入市场之后非常畅销,于是在利益的驱使下,他决定要 “炒书”! 
 
题目描述:
炒书和炒股类似,kk 已经提前知道了每一天的书价,从第 1 天到第 n 天分别记 为   …  , 他每次只能同时持有一张股票。 书商看不惯kk 的行为,于是限制了 kk 的交易,当 kk 被限制时他最多只能买一 次书和卖一次书。 kk想知道他最多能赚多少钱? 
 
输入格式: 
第一行两个数:n、m 分别表示天数和是否限制交易(1 表示限制) 第二行 n 个数,第 i 个数是   ai
输出格式: 
一个数表示最多的利润 
 
6 0
1 3 2 0 7 9 
 
 11 
 
数据范围: 
所有数据均为非负整数
对于 30%的数据 n<=1000
对于 60%的数据 m=1,n<=1000000
对于 100%的数据 m=0,n<=1000000
书价不大于 1000
__________________________________________________________________________________________________________________________________________________________________________________________________________________
当 m = 1 时 思路:定义一个结构体,存放书价以及第几天(编号)。把结构体按书价从小到大排序。定义 i 从前往后找,j 从后往前找,判断是否符合要求(买的天数必须在卖的天数前面,也就是 a[i] 的编号 < a[j] 的编号)如果符合要求,求出 a[j] 和 a[i] 的差值,答案已经找到了,跳出循环。如果不符合要求,继续 i++ 或 j--。i++ 还是 j-- 取决于两个差值 a[j-1] - a[i] 和 a[j] - a[i+1] 的大小,哪个差值大就说明能哪个能赚更多的钱
当 m = 0 时 思路:一个循环,当 a[i+1] > a[i] 时,把它们的差值加入答案ans中
 
还看到了一种非常巧妙的方法,这种方法在 m = 1 时从 n 到 1 倒序循环,排除了 max 值在 a[i] 在左边的情况
 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cstdio>
 5 using namespace std;
 6 const int N=1e6+10;
 7 int n,m;
 8 long long ans,a[N];
 9 int main(){
10     freopen("book.in","r",stdin);
11     freopen("book.out","w",stdout);
12     cin>>n>>m;
13     for(int i=1;i<=n;i++)cin>>a[i];
14     if(m){
15         long long mx=a[n];
16         for(int i=n-1;i;i--){
17             ans=max(ans,mx-a[i]);
18             mx=max(mx,a[i]);
19         }
20     }
21     else for(int i=2;i<=n;i++){
22         if(a[i]>a[i-1])ans+=a[i]-a[i-1];
23     }
24     cout<<ans<<endl;
25     return 0;
26 }
巧妙的方法
原文地址:https://www.cnblogs.com/frank06/p/10389503.html