1302:股票买卖
【题目描述】
最近越来越多的人都投身股市,阿福也有点心动了。谨记着“股市有风险,入市需谨慎”,阿福决定先来研究一下简化版的股票买卖问题。
假设阿福已经准确预测出了某只股票在未来N天的价格,他希望买卖两次,使得获得的利润最高。为了计算简单起见,利润的计算方式为卖出的价格减去买入的价格。
同一天可以进行多次买卖。但是在第一次买入之后,必须要先卖出,然后才可以第二次买入。
现在,阿福想知道他最多可以获得多少利润。
【输入】
输入的第一行是一个整数T(T≤50),表示一共有T组数据。
接下来的每组数据,第一行是一个整数N(1≤N≤100,000),表示一共有N天。第二行是 N 个被空格分开的整数,表示每天该股票的价格。该股票每天的价格的绝对值均不会超过1,000,000。
【输出】
对于每组数据,输出一行。该行包含一个整数,表示阿福能够获得的最大的利润。
【输入样例】
3
7
5 14 -2 4 9 3 17
6
6 8 7 4 1 -2
4
18 9 5 2
【输出样例】
28
2
0
#include<bits/stdc++.h>
using namespace std;
//因为当天的股票可买卖 有点像登山或是合唱队形
//当前股票与前面最小值的差加上当前股票与后面最大值的差,取最大的那个
int n,t,fl[100005],fh[100005],a[100005];
//fl是取从左最小值的到每天的利润 fh是取从右最大值时到每天的利润
int main()
{
int minx,maxy;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
minx=a[1]; maxy=a[n];
for(int i=1;i<=n;i++){//当前与前面最小值的利润
minx=min(minx,a[i]);
fl[i]=max(fl[i-1],a[i]-minx);//取个前面的大值
}
fh[n+1]=0;//因为不是一组数,防这个位有数
for(int i=n;i>=1;i--)//当前与后面最大值的利润
{
maxy=max(maxy,a[i]);//取个后面的大值
fh[i]=max(fh[i+1],maxy-a[i]);
}
maxy=0;
for(int i=1;i<=n;i++)//找到最大值
maxy=max(maxy,fl[i]+fh[i]);
printf("%d\n",maxy);
}
}
1305:Maximum sum
【题目描述】
对于给定的整数序列A={a1,a2,...,an},找出两个不重合连续子段,使得两子段中所有数字的和最大。1≤s1≤t1<s2≤t2≤n,就是求最大(s1到t1最大子段和s2到t2最大子段和相加)
【输入】
第一行是一个整数T(≤30),代表一共有多少组数据。
接下来是T组数据。
每组数据的第一行是一个整数,代表数据个数据n(2≤n≤50000) ,第二行是n个整数a1,a2,...,an(|ai|≤10000)。
【输出】
输出一个整数。
【输入样例】
1
10
1 -1 2 2 3 -3 4 -4 5 -5
【输出样例】
13
/*以i分数组,i前的最大子段和与i+1到n的最大子段和,找出最大和的值
从左到每位上的最大子段和,如前面求得的和大于0,可加在当前位上,否则只是当前位上的值
从右到每位上的最大子段和,如后面的子段和大于0,可加在当前位上,否则只是当前位上的值 */
#include<bits/stdc++.h>
using namespace std;
int fl[50005],fr[50005],n,t,a[50005];
//fl是从左开始的到每位的最大子段和
//fr是从右开始到每位的最大子段和
int main()
{
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++)//
scanf("%d",&a[i]);
//从左到每个位的最大子段和
for(int i=1;i<=n;i++)
if(fl[i-1]<=0) fl[i]=a[i];
else fl[i]=fl[i-1]+a[i];
//从右到左到每位上的最大子段和
fr[n+1]=0;//以防这里有数
for(int i=n;i>1;i--)
if(fr[i+1]<=0) fr[i]=a[i];//如果比0小,就不加上它了
else fr[i]=fr[i+1]+a[i];
int maxx=-0x3e3e3e3e;
int maxy=maxx;
for(int i=1;i<n;i++)//以i为分点
{
maxx=max(maxx,fl[i]);//到每个位的最大子段和
maxy=max(maxy,maxx+fr[i+1]);//前后两个子段和
}
cout<<maxy<<endl;
}
}