gfoj_704 数组操作

http://www.gdfzoj.com/oj/contest/159/problems/3

Problem 704: 数组操作
Time Limit: 1000 ms Memory Limit: 262144 KB

Problem Description
给出n个数组,每个数组有Li个整数,将数组编号为1,2,3,…,n,然后给出m个数,每个数均为之前数组的编号,将这些数组按照给出的编号顺序连接起来,形成新的数组,比如:给出以下三个数组[1,6,-2],[3,3],[-5,1],然后给出编号2 3 1 3,则新数组为[3,3,-5,1,1,6,-2,-5,1],现在请问新数组的最大连续子序列和是多少。

Input
第一行两个正整数n,m。

接下来n行,每行第一个数为Li,之后Li个整数。

最后一行有m个正整数,表示连接数组顺序的编号。

【数据范围】

对于10%的数据,形成的数组长度不超过100000

对于100%的数据,1 <= n <= 50,1 <= Li <= 5000,1 <= m <= 250000,每个数组中的数绝对值在1000以内

Output
一行一个数,表示最大连续子序列和。

Sample Input
3 4

3 1 6 -2

2 3 3

2 -5 1

2 3 1 3

Sample Output
9

[3,3,-5,1,1,6,-2,-5,1],红色部分为最大和的连续子序列。

Problem Source
2017提高组联赛训练7.10

分析

如果暴力的话只能拿三十分(亲自试验tle)

所以我们可以预处理处每个数组的左区间和,最大连续子段和,右区间和,区间和

然后O(n)两次动态规划

然后每个区间统计答案即可

注:子段和至少要选取一个元素,即如果询问的区间全部都是负数,那么输出的答案为最小的那个负数的值

吐槽一下gfoj数据太弱,非负都a了

ac代码

#include<cstdio>
#include<iostream>
#include<cstring>
#define N 60
#define M 250010
#define INF 9000000000000000000
using namespace std;
typedef long long LL;
int a[M],n,m,s;
LL ans,f[M][2],sum[N],sub[N],rma[N],lma[N],num;
int main(){
    freopen("data.txt","r",stdin);
    memset(lma,-0x7f,sizeof(lma));
    memset(rma,-0x7f,sizeof(rma));
    memset(sub,-0x7f,sizeof(sub));
    ans=-INF;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&s);
        for(int j=1;j<=s;j++)scanf("%d",&a[j]);
        num=0;
        for(int j=1;j<=s;j++){
            num+=a[j];
            lma[i]=max(lma[i],num);
        }
        num=0;
        for(int j=s;j>=1;j--){
            num+=a[j];
            rma[i]=max(rma[i],num);
        }
        num=0;
        for(int j=1;j<=s;j++){
            sum[i]+=a[j];
            num=max(num+a[j],(LL)a[j]);
            sub[i]=max(sub[i],num);
        }
//      cout<<lma[i]<<' '<<sub[i]<<' '<<rma[i]<<' '<<sum[i]<<'\n';
    }
    for(int i=1;i<=m;i++)scanf("%d",&a[i]);
    for(int i=1;i<=m;i++)f[i][0]=max(f[i-1][0]+sum[a[i]],rma[a[i]]);
    for(int i=m;i>=1;i--)f[i][1]=max(f[i+1][1]+sum[a[i]],lma[a[i]]);
    for(int i=0;i<=m;i++)ans=max(ans,max(sub[a[i]],f[i][0]+f[i+1][1]));
    cout<<ans;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章