首页 > 试题广场 >

编程题2

[编程题]编程题2
  • 热度指数:4356 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 128M,其他语言256M
  • 算法知识视频讲解

给定一个数组序列, 需要求选出一个区间, 使得该区间是所有区间中经过如下计算的值最大的一个:

区间中的最小数 * 区间所有数的和最后程序输出经过计算后的最大值即可,不需要输出具体的区间。如给定序列  [6 2 1]则根据上述公式, 可得到所有可以选定各个区间的计算值:

 

[6] = 6 * 6 = 36;

[2] = 2 * 2 = 4;

[1] = 1 * 1 = 1;

[6,2] = 2 * 8 = 16;

[2,1] = 1 * 3 = 3;

[6, 2, 1] = 1 * 9 = 9;

 

从上述计算可见选定区间 [6] ,计算值为 36, 则程序输出为 36。

区间内的所有数字都在[0, 100]的范围内;


输入描述:
第一行输入数组序列长度n,第二行输入数组序列。
对于 50%的数据,  1 <= n <= 10000;
对于 100%的数据, 1 <= n <= 500000;


输出描述:
输出数组经过计算后的最大值。
示例1

输入

3
6 2 1

输出

36
完美AC。
最大值区间的最小值必定是数组的某个数。对于数组的第 i 个数,以该数为中心,分别向左右两边探测直到遇到比该数小的数停止,探测过程中可同时累加探测到的数,探测结束后累加得到的和乘以该数便得到了以该数为最小值所能得到的区间的最大值。依次遍历数组的每个数,更新得到的最大值即可。
#include <iostream>
using namespace std;
int main()
{
    int N;
    while(cin>>N)
    {
        int arr[N];
        for (int i=0; i<N; i++)
            scanf("%d",&arr[i]);
        int max=0;
        for (int i=0; i<N; i++)
        {
            int val=0;
            int j=i;
            while(j<N && arr[j]>=arr[i])
            {
                val+=arr[j];
                j++;
            }
            j=i-1;
            while(j>=0 && arr[j]>=arr[i])
            {
                val+=arr[j];
                j--;
            }
            if (arr[i]*val>max)
                max=arr[i]*val;
        }
        printf("%d\n", max);
    }
    return 0;
}

发表于 2018-05-10 17:23:44 回复(7)
#include<iostream>
using namespace std;
 
int main()
{
    int n;
    cin>>n;
    int *array = new int[n];
    for(int i=0; i<n; ++i)
        cin>>array[i];
    int nMax = array[0]*array[0];
    for(int i=0; i<n; ++i)
    {
        int sum = 0;
        int minN = array[i];
        for(int j=i; j<n; ++j)
        {
            if(array[j]==0) break;
            sum += array[j];
            if(minN>array[j])
                minN = array[j];
            if(minN*sum>nMax)
                nMax = minN*sum;
        }
    }
    cout<<nMax;
}
如果缺少if(array[j]==0) break;程序的运行时间是3s,只能通过60%的测试用例。

发表于 2018-06-19 09:40:59 回复(0)
直接暴力。
对于数组中的每个数,以这个数为中心,寻找以这个数为最小值的最大区间。不断更新最大值即可。

代码如下:
#include<bits/stdc++.h>
using namespace std;

#define LL long long
const int maxn=5e5+5;

int num[maxn],sum[maxn];
LL result;

void solve(int n)
{
    int left,right;
    for(int i=1;i<=n;++i)
    {
        left=right=i;
        while(num[--left]>=num[i]&&left>0); //寻找左端点
        while(num[++right]>=num[i]&&right<=n); //寻找右端点
        result=max(result,(LL)num[i]*(sum[right-1]-sum[left]));
    }
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&num[i]);
        sum[i]=num[i]+sum[i-1];  //前缀和
    }
    result=0;
    solve(n);
    printf("%lld\n",result);
    return 0;
}

发表于 2019-04-27 11:05:11 回复(0)

使用单调栈,可以通过全部测试用例

#include 
#include 
#include 
using namespace std;

int findMax(vector v) {
    int len = v.size(), res = 0;
    vector sum(len + 1, 0);
    for (int i = 1; i <= len; ++i) sum[i] = sum[i-1] + v[i-1];
    stack s;
    for (int i = 0; i < len; ++i) {
        while (!s.empty() && v[i] < v[s.top()]) {
            int index = s.top(), left, right = i;
            s.pop();
            if (s.empty()) left = 0;
            else left = s.top() + 1;
            // cout << v[index] * (sum[right] - sum[left]) << endl;
            res = max(res, v[index] * (sum[right] - sum[left]));
        }
        s.push(i);
    }
    while(!s.empty()) {
        int index = s.top(), left, right = len;
        s.pop();
        if (s.empty()) left = 0;
        else left = s.top() + 1;
        // cout << v[index] * (sum[right] - sum[left]) << endl;
        res = max(res, v[index] * (sum[right] - sum[left]));
    }
    return res;
}

int main() {
    // vector v{6,2,5,5,5,4,7};
    int n;
    cin >> n;
    vector v(n);
    for (int i = 0; i < n; ++i) scanf("%d", &v[i]);
    cout << findMax(v) << endl;
}
发表于 2018-07-30 20:23:11 回复(1)
int solution(vector<int>& nums){
        //加一个0保证所有元素都出栈
        nums.push_back(0);
        int n = nums.size(), res = 0 ;
        vector<int> preSum(n+1, 0);
        vector<int> st;
        for(int i = 1; i <= n; ++i) 
            preSum[i] = preSum[i-1] + nums[i-1];
        for(int i = 0; i <= n; ++i){
            while(!st.empty() && nums[st.back()] >= nums[i]){
                int cur = nums[st.back()];
                st.pop_back();
                int l = st.empty()? -1: st.back();
                res = max(cur*(preSum[i] - preSum[l+1]), res);
            }
            st.push_back(i);
        }      
        return res;
}
发表于 2021-12-30 11:31:08 回复(0)
Java已AC,通过所有测试用例
import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
        //System.out.println(123);
        Scanner scanner = new Scanner(System.in);
        int num = scanner.nextInt();
        int[] arr = new int[num];
        for(int i = 0; i < num; i++){
            arr[i] = scanner.nextInt();
        }
        int max = 0;
        for(int i = 0; i < num; i++){
            int sum = arr[i], value = arr[i], left = i - 1, right = i + 1;
            while(left >= 0 && arr[left] >= value){
                sum += arr[left];
                left--;
            }
            while(right < num && arr[right] >= value){
                sum += arr[right];
                right++;
            }
            max = Math.max(max, value * sum);
        }
    System.out.println(max);
    }
}


编辑于 2020-08-14 15:36:02 回复(0)
看了大家的解析之后运行出来了,每次循环的时候查找以当前元素为最小值的集合,然后计算该集合元素的值与之前的max比较即可
n=int(input().strip())
arr=list(map(int,input().strip().split(' ')))
summax=max(arr)**2
for i in range(n):
    cusum=arr[i]
    l,r=i-1,i+1
    if arr[i]==0:
        continue
    while l>=0 and arr[l]>=arr[i]:
        cusum+=arr[l]
        l-=1
    while r<=n-1 and arr[r]>=arr[i]:
        cusum+=arr[r]
        r+=1
    summax=max(summax,arr[i]*cusum)
print(summax)


发表于 2019-08-08 14:57:00 回复(2)
#第一次求整个数列和乘最小值,以最小值划分成左右两个数组继续求和乘最小值
#include<iostream>
#include <algorithm>
usingnamespacestd;
intfind(inta[],intright,intleft,intmax){
   if(right<=left){
       inti=right;
        intj=left;
        intt,sum=0,temp,ax;
        temp=a[i];
        ax=i;
        sum=a[i];
        for(t=i+1;t<=j;t++){
            sum=sum+a[t];
            if(a[t]<temp){
                temp=a[t];
                ax=t;
            }
        }
        if(max<(sum*temp)){
            max=sum*temp;
        }
        max=find(a,i,ax-1, max);
        max=find(a,ax+1,j, max);
   }
    returnmax;
}
 
intmain (){
    intn,m,i;
    cin>>n;
    inta[n];
    for(i=0;i<n;i++){
        cin>>a[i];
    }
    m=find(a,0,n-1,0);
    cout<<m;
    return0;
}
发表于 2019-03-14 21:55:49 回复(0)
public static void main(String args[]){
        Scanner sc = new Scanner(System.in);
        int size = sc.nextInt();
        int [] input  =new int [size];
        for(int i=0;i<input.length;i++){
            input[i] = sc.nextInt();
        }

        long max=input[0]*input[0];
        for(int i=0;i<size;i++){
             long sum=input[i];
             int min=input[i];
            for(int j=i+1;j<size;j++){
                if(input[j]==0){
                    break;
                }
                sum+=input[j];
                if(input[j]<min){
                    min = input[j];
                }
                if(min*sum>max){
                    max=min*sum;
                }
            }
        }
        System.out.println(max);
    }
  • 直接写,通过,不知道有什么好算法。
发表于 2018-01-01 20:10:28 回复(2)
if __name__ == "__main__":
    n = int(input())
    inlist = list(map(int,input().split()))

    res = 0
    for i in range(n):
        tmp = inlist[i]
        if tmp == 0:
            continue
        l = r = i
        while l - 1 >= 0 and inlist[l - 1] >= tmp:
            l -= 1
        while r + 1 < n and inlist[r + 1] >= tmp:
            r += 1
        res = max(res, tmp * sum(inlist[l:r + 1]))
    print(res)

遍历每个数,并找出该数的最大区间,即该数在区间中最小,加总求积,已AC

编辑于 2019-08-14 08:21:30 回复(0)
思路:
给定序列  [6 2 1 3],从前往后遍历,i 指向第一个元素,j 指向后面的元素,计算区间 【i,j】的最大值。
过程如下:
  1. 第一次循环:依次计算【6】、【6,2】、【6,2,1】、【6,2,1,3】
  2. 第二次循环:依次计算【2】、【2,1】、【2,1,3】
  3. 第三次循环:依次计算【1】、【1,3】
  4. 第四次循环:依次计算【3】
#include <bits/stdc++.h>
using namespace std;
#define nullptr NULL

int main()
{
    freopen("data.in","r", stdin);
    int n;
    scanf("%d", &n);
    int a[n];
    for(int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }

    int curMax = a[0] * a[0];
    for(int i = 0; i < n; i++) {
        int curMin = a[i];
        int curSum = 0;
        for(int j = i; j < n; j++) {
            if(a[j] == 0) break;    // 遇到 0, 就 break 
            curSum += a[j];
            if(a[j] < curMin) curMin = a[j];
            int sum = curMin * curSum; 
            if(sum > curMax)
                curMax = sum;
        }
    }

    printf("%d\n", curMax);

    return 0;
}

发表于 2018-03-24 15:23:33 回复(1)
N = int(input())
line = list(map(int, input().split()))
# print line
curMax = line[0] * line[0]
 
for i in range(N):
    curmin = line[i]
    cursome = 0
    for j in range(i,N):
        if line[j] == 0:
            break
        cursome += line[j]
        if line[j]< curmin:
            curmin = line[j]
        max=  curmin* cursome
        if max> curMax:
            curMax = max
        
 
print( curMax)
发表于 2020-05-11 22:07:03 回复(0)
num = int(input())
list1= (input().split())
for i in range (0,len(list1)):
    list1[i]=int(list1[i])
print (list1)
list2 = []
for j in range (0,num):
     for k in range (j, num):   
            summary = sum(list1[j:k+1])
            list2.append(summary*min(list1[j:k+1]))
print (max(list2))
萌新尝试了这个,因为python代码真的学的太浅只能这么写,为啥只过20%qwq
发表于 2020-04-12 15:10:54 回复(0)
'''最大区间'''
#以i点为最小值
n = int(input())
nums = list(map(int,input().split()))
res = 0
for i in range(n):
    cur_sum = nums[i]
    #不加超时
    if cur_sum==0:
        continue
    j = i+1
    while j<n and nums[i]<=nums[j]:
        cur_sum += nums[j]
        j += 1
    j = i-1
    while j>=0 and nums[i]<=nums[j]:
        cur_sum += nums[j]
        j -= 1
    res = max(res,cur_sum*nums[i])

print(str(res))

发表于 2019-09-07 17:26:45 回复(0)

n = int(raw_input())

data_list= [int(x) for x in raw_input().split(' ')]
leng = len(data_list)
result = []
maxflag = 0
data_list = sorted(data_list,reverse=True)

for i in range(leng):
    if i == 0:
        result.append(data_list[0]**2)
    else:
        a = data_list[:i+1]
        result.append(min(a)*sum(a))
print result
print max(result)



是我对题目理解有误吗,按理来说要求最大值,不应该用最大的数来求吗
所以先将这串数从大到小排列
对于1个数的区间,就直接是第一个数的平方
对于i个数的区间,就是取前i个数的最小值乘以这i个数的和

不知道为啥代码老提示有语法错误,明明自测没问题
发表于 2019-07-17 16:35:52 回复(0)

python3 通过

import  sys
n = int(sys.stdin.readline().strip())
nums =  list(map(int, sys.stdin.readline().strip().split()))
summax = nums[0] ** 2
for i in range(0,len(nums)):
    if nums[i]==0:#没有这判断python会超时
        continue
    cursum = nums[i]
    l ,r = i-1,i+1
    while l>=0 and nums[l]>=nums[i]:
        cursum +=nums[l]
        l-=1
    while r = nums[i]:
        cursum += nums[r]
        r += 1
    temp = nums[i] * cursum
    if temp > summax:
        summax = temp
print(summax)  
编辑于 2019-07-08 17:26:41 回复(0)
单调栈维护左边和右边第一个比它小的位置
#include <bits/stdc++.h>
	
using namespace std; const int N = 5e5+5; int a[N],L[N],R[N],prefix[N]; int main(){     int n;     scanf("%d",&n);     for(int i=1;i<=n;i++){         scanf("%d",&a[i]);         prefix[i] = prefix[i-1]+a[i];         L[i] = 0,R[i] = n+1;     }     stack <int> stk; /// 维护一个从栈低到栈顶的递增区间     for(int i=1;i<=n;i++){         while(!stk.empty() && a[stk.top()] >= a[i]) stk.pop(); /// 找到左边第一个小于它的位置         if(stk.size()) L[i] = stk.top();         stk.push(i);     }     while(!stk.empty()) stk.pop();     for(int i=n;i>=1;i--){         while(!stk.empty() && a[stk.top()] >= a[i]) stk.pop(); /// 找到右边第一个小于它的位置         if(stk.size()) R[i] = stk.top();         stk.push(i);     }     int ans = 0;     for(int i=1;i<=n;i++){         ans = max(ans , (prefix[R[i]-1] - prefix[L[i]])*a[i]);     }     printf("%d\n",ans);     return 0; }

编辑于 2019-04-28 21:51:09 回复(0)
n = int(input())

nums = list(map(int, input().strip().split()))
res = 0
for i in range(n):
    # 取当前值为最小值
    min_ = nums[i]
    sum_ = nums[i]
    res = max(res, nums[i] * nums[i])
    for j in range(i + 1, n):
        # 更新最小值
        min_ = min(min_, nums[j])
        sum_ += nums[j]
        res = max(res, min_*sum_)
print(res)

求助!!
思路:i指向当前数字,j指向i之后的数字,遍历整个数组。通过率只有60%,请问代码该怎么完善呀?谢谢各位大佬!!
发表于 2019-03-15 15:59:15 回复(0)
N = int(input())
a=[int(i) for i in input().split()]
b=a.copy()
a.sort()
M=a[N-1]*a[N-1]
M2=a[0]*sum(a)
if M<M2:
    M=M2
def getmax(x,y):
    global M
    tmp=0
    newlist=[]
    for i in range(y):
        if x+i<N:
            newlist.append(b[x+i])
    newlist.sort()
    tmp=sum(newlist)*newlist[0]
    if tmp>M:
        M=tmp
    if x+y<=N:
        getmax(x+1,y)

for i in range(2,N):
    getmax(0,i)

print(M)
只通过了20%不知道哪里错了
发表于 2019-03-14 16:08:40 回复(0)