DP算法
1.题目大意
就是 T T T 组数据,每个数据一个 n n n 和一个数组找出相邻两项异号并且长度最大、各项之和最大的子序列。
2.思路
看到这个题,首先可以想到 B 3637 B3637 B3637 最长上升子序列这个题,只需要改一下中间 d p [ ] dp[] dp[] 的转移方程,并把取最大改为求和,当然 d p [ i ] dp[i] dp[i] 的意义也有改变。
d p [ i ] dp[i] dp[i] 表示第 i i i 个数应取的数。
转移方程:
( p o s pos pos 表示 d p dp dp 取到第几个数了)
如果 d p [ p o s ] dp[pos] dp[pos] 和 a [ i ] a[i] a[i] 是同号,则比较 d p [ p o s ] dp[pos] dp[pos] 与 a [ i ] a[i] a[i] 的大小,取大的值。
如果 d p [ p o s ] dp[pos] dp[pos] 和 a [ i ] a[i] a[i] 是异号,则 p o s + 1 pos+1 pos+1, d p [ p o s ] dp[pos] dp[pos] 等于 a [ i ] a[i] a[i]。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int a[N],n,dp[N],maxi=-1e9,T;
int main()
{
cin>>T;
while(T--)//T组数据
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
dp[i]=a[i];
}
dp[1]=a[1];
int pos=1;//dp[]去到第几个数了
for(int i=2;i<=n;i++)
{
if((a[i-1]<0&&a[i]<0)||(a[i-1]>0&&a[i]>0))//转移
dp[pos]=max(dp[pos],a[i]);
else
dp[++pos]=a[i];
}
long long sum=0;//切记开long long
for(int i=1;i<=pos;i++)
sum+=dp[i];//求和
cout<<sum<<"\n";
}
return 0;
}