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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章