2018今日头条笔试(第二题)

题目描述

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

区间中的最小数 * 区间所有数的和

最后程序输出经过计算后的最大值即可,不需要输出具体的区间。如给定序列[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

则程序输出36

区间所有数字都在【0,100】的范围内。

解题思路:

可以看出我们需要维护一个区间,同时我们能知道区间的最小值,和这个区间所有数字的和。

但是,有一点我们可以清楚知道,如果一个区间的最小值已经确定,那么我们就要尽量使得区间的和最大。其实本问题就可以转换到遍历数组,以当前位置为最小值,向左向右>=当前值能扩展的最大距离问题,我们知道这样的方法时间复杂度是O(n^2)。

嗯 区间的最小值和区间边界我们可以用单调栈去维护,这样时间复杂度就降到O(n)

其实大小都有了,输出区间边界也就不难了。我这里 输出了最大值和 区间的开始结束位置。如果有多个区间=max,我输出的是字典序较小的区间,代码如下:

给几个比较有用的数据

1

0

ans:

0

1 1

---------------------

9

1 1 1 1 1 1 1 2 2

ans:

11

1 9

----------------

4

1 3 2 4

ans:

18

2 4

----------------

#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
typedef long long ll;
ll a[100010];
class node {
    public:
        ll left, right,x;
};
ll sum[100010];
int main() {
    // 维护一个递增的栈
    int n;
    vector<node> st;
    while (cin>>n) {
        ll ans = -1;
        if (n == 0) {
            cout << 0 << endl << 0 << " " << 0 << endl;continue;
        }
        ll l = 0,  r = 0;
        while (!st.empty()) st.pop_back();
        sum[0] = 0;
        for (int i = 1; i <= n; ++i) {
            scanf("%lld",&a[i]);
            sum[i] = sum[i-1] + a[i];
        }
        for (int i = 1; i <= n; ++i) {
            if (st.empty()) {
                st.push_back({i,i,a[i]});
            } else {
                node u = st.back();
                if (a[i] > u.x) {
                    st.push_back({i,i,a[i]});
                } else {
                    int ileft=0,iright=0;
                    while (!st.empty()) {
                        node v = st.back();
                        if (v.x >= a[i]) {
                            st.pop_back();
                            ileft = v.left;
                            if(st.size()) st.back().right = v.right;
                            ll tmp = (sum[v.right] - sum[v.left-1])*v.x;
                            if (tmp >= ans) {
                                ans = tmp;
                                l = v.left;
                                r = v.right;
                            }
                        } else break;
                    }
                    st.push_back({ileft,i,a[i]});
                }
            }
        }
        while (!st.empty()) {
            node v = st.back();
            st.pop_back();
            if(st.size()) st.back().right = v.right;
            ll tmp = (sum[v.right] - sum[v.left-1])*v.x;
            if (tmp >= ans){
                ans = tmp;
                l = v.left;
                r = v.right;
            }
        }
        cout << ans << endl << l << " " << r << endl;
    }
    return 0;
}
时间: 2024-10-08 22:59:20

2018今日头条笔试(第二题)的相关文章

【实习生求职】今日头条笔试

时间:大三下学期 职位:测试开发 过程: 首先,会有练习题,但是练习题没有针对性,而且编程题会很简单:主要是用来检查自己的环境是否合适.熟悉系统. 然后就是正式考试了--开始会很卡(反正我是连题都加载不出来),之后会正常(偶有卡顿). 题目不难(然而本人菜鸟就呵呵了),一共四个--写一个12306系统购票模块的测试用例,查找第一个出错版本(不知道是不是我理解错了,感觉这题很奇怪),两个编程题.编程题本人跪了.究其原因,主要是两条--本人没有系统的学习过算法,也没有批量的练习过编程题,个人技术不过

8.22 今日头条笔试

这次套路深啊,怎么还有改错题!. 上来看题,每个题目的输入数据都很大,果断上scanf,printf, 千万不能用cin,cout 1. 右上角的点,我的思路是先对每一行去重(题目好像说没有重的点耶!),每一行只有最右边的点才是候选点,然后对这些候选点按照y坐标,从大到小访问,要求相应的x是严格递增的,最后打印输出. 1 #include<bits/stdc++.h> 2 #define pb push_back 3 typedef long long ll; 4 using namespac

网易前端笔试第二题2017

import java.util.*; /*把并列的两个整数(中间用空格隔开)倒转,并去掉开头的0,然后将两个结果合起来再倒转,去0: * 输入:123 234 * 输出:234123 * 输入:10020 123 * 输出: 1231002*/ public class daozhuan { public static void main(String[] args){ Scanner cin = new Scanner(System.in); String str = cin.nextLin

2018今日头条春招的一道笔试题 —— 通过改变枚举的变量进行枚举优化

题目如下: 这道题我们最先想到的做法,应该就是2重循环枚举数对,然后把数对放在set里去重,最后输出set的大小,即输出set.size( ).代码如下: 1 #include<iostream> 2 #include<set> 3 using namespace std; 4 5 int n, k, a[100000]; 6 set<pair<int, int>> mypairs; 7 8 int main() 9 { 10 cin >> n

2018今日头条

P为给定的二维平面整数点集.定义 P 中某点x,如果x满足 P 中任意点都不在 x 的右上方区域内(横纵坐标都大于x),则称其为"最大的".求出所有"最大的"点的集合.(所有点的横坐标和纵坐标都不重复, 坐标轴范围在[0, 1e9) 内) 如下图:实心点为满足条件的点的集合.请实现代码找到集合 P 中的所有 "最大" 点的集合并输出. 输入描述: 第一行输入点集的个数 N, 接下来 N 行,每行两个数字代表点的 X 轴和 Y 轴. 对于 50%的

2018春招-今日头条笔试题-第三题(python)

题目描述:2018春招-今日头条笔试题5题(后附大佬答案-c++版) 解题思路: 本题的做法最重要的应该是如何拼出'1234567890',对于输入表达试获得对应的结果利用python内置函数eval()即可以实现.利用5个字符串来表达'1234567890',如下(为了好看,里面加了tab空格符) '66666 ....6 66666 66666 6...6 66666 66666 66666 66666 66666''6...6 ....6 ....6 ....6 6...6 6.... 6

今日头条&amp;58转转笔试

昨天参加今日头条和58转转的笔试,因为时间上有冲突,所以主要选择参加头条的笔试. 先说头条: 头条的题型: 一道改错题 三道编程题 一道设计题 感受: 做题目的的时候还是有点紧张的,因为突然遇到题目需要思考很长时间,而且不确定是否正确时,真的是着急. 做完头条笔试感觉真是好大差距,有大神三道编程全部AC,而我三道编程只能50%,0,0: 改错题一上来有点懵,半个多小时,最后还不知道改的对不对. 设计题基本是用一个套路来回答的,也不确定,但肯定不完善. 被虐的体无完肤. 下面主要记一下编程题: 第

2017年校招全国统一模拟笔试(第二场)编程题集合-牛客网

 2017年校招全国统一模拟笔试(第二场)编程题集合-牛客网 链接:https://www.nowcoder.com/questionTerminal/276712b113c6456c8cf31c5073a4f9d7来源:牛客网 牛牛有两个字符串(可能包含空格),牛牛想找出其中最长的公共连续子串,希望你能帮助他,并输出其长度. 输入描述: 输入为两行字符串(可能包含空格),长度均小于等于50. 输出描述: 输出为一个整数,表示最长公共连续子串的长度. 输入例子: abcde abgde 输出例子

最全BAT算法面试100题:阿里、百度、腾讯、京东、美团、今日头条

第一:复杂度估算和排序算法(上)1) 时间复杂度和空间复杂度 2)认识对数器 3)冒泡排序 4)选择排序 5)插入排序 6)如何分析递归过程的时间复杂度 7)归并排序 8)小和问题 第二:复杂度估算和排序算法(下)1)荷兰国旗问题 2)随机快速排序 3)堆结构与堆排序 4)认识排序算法的稳定性 5)认识比较器 6)桶排序 7)计数排序 8)基数排序 9)数组排序后的最大差值问题 10)排序算法在工程中的应用 第三:章栈.队列.链表.数组和矩阵结构1)栈结构 2)队列结构 3)链表结构 4)数组结