我也真佩服自己能用dp写…
//dp[i][t]表示前i个数的最大值,且i在t状态这个区间
void transfrom(int i,int t)
{
int is=(t%2==1?1:-1);//这个区间的符号是is
for(int j=1;j<=t;j++)//只能从dp[i-1][j]转移,j小于等于t
if(dp[i-1][j]+a[i]*is>dp[i][t])
dp[i][t]=dp[i-1][j]+a[i]*is,pre[i][t]=j;//pre数组记录前驱
}
int num=1,maxx=dp[n][1];
for(int i=2;i<=4;i++)
if(maxx<dp[n][i]) maxx=dp[n][i],num=i;//找出最大的状态
for(int i=n;i>=1;i--)//现在的任务就是倒推回去找出每个点的状态
{
flag[i]=num;//储存各个点所在的区间
num=pre[i][num];
}
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=5009;
int d0=0,d1=0,d2=0,flag[maxn];
int n,a[maxn],pre[maxn][5],dp[maxn][5];
void transfrom(int i,int t)
{
int is=(t%2==1?1:-1);
for(int j=1;j<=t;j++)//从上一个状态的j状态转移而来
if(dp[i-1][j]+a[i]*is>dp[i][t])
dp[i][t]=dp[i-1][j]+a[i]*is,pre[i][t]=j;
}
void init()
{
for(int i=1;i<=5000;i++)//注意dp[0][...]仍然保持是0!!
for(int j=0;j<=4;j++) dp[i][j]=-1e18;
}
signed main()
{
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i];
init();//初始赋值无穷小
for(int i=1;i<=n;i++)
for(int j=1;j<=4;j++) transfrom(i,j);//开始dp
int num=1,maxx=dp[n][1];
for(int i=2;i<=4;i++)
if(maxx<dp[n][i]) maxx=dp[n][i],num=i;//找出最大的
for(int i=n;i>=1;i--)//现在的任务就是倒推回去找出每个点的状态
{
flag[i]=num;//储存各个点所在的区间
num=pre[i][num];
}
for(int i=1;i<=n;i++)
{
if(flag[i]==1&&flag[i+1]!=1) d0=i;
if(flag[i]==2&&flag[i+1]!=2) d1=i;
if(flag[i]==3&&flag[i+1]!=3) d2=i;
}
if(d0==0) d0=0;
if(d1==0) d1=d0;
if(d2==0) d2=n;
cout<<d0<<" "<<d1<<" "<<d2;
}