• 最长连续子序列(贪心)


    题意

    给定一个长度为\(n\)的整数序列\(a_1, a_2, \dots , a_n\)

    现在,请你找到一个序列\(a\)的连续子序列\(a_l,a_{l+1}, \dots ,a_r\),要求:

    • \(\sum\limits_{i=l}^r a_i > 100 \times (r−l+1)\)
    • 连续子序列的长度(即\(r−l+1\))尽可能大。

    请你输出满足条件的连续子序列的最大可能长度。

    题目链接:https://www.acwing.com/problem/content/4490/

    数据范围

    \(1 \leq n \leq 10^6\)

    思路

    第一个条件要求均值大于\(100\),因此可以按照常规套路将每个元素减去\(100\),条件就转化为了连续子序列和大于\(0\)

    如何快速判断连续子序列和是否大于\(0\)呢?可以考虑前缀和,记为\(s\)。若\(s_j > s_i\)\(i < j\),则\(a[i,j]\)的连续子序列和大于\(0\)

    问题就转化为了,找到最大的\(j - i\),满足\(s_j > s_i\)

    对于这种问题,我们可以通过排序固定一个条件,这样就只需要看一个条件了。在这里,按照\(s\)从小到大排序(注意每个元素初始下标要记录下来),如果\(s_i = s_j\)则初始下标大的放在前面。

    扫描排序后的序列,维护前缀初始下标最小值,如果当前元素的初始下标大于前缀初始下标最小值,则更新答案。(这样满足了后面的一定比前面的大,如果两者相等是不会更新答案的,因为下标大的在前)。

    代码

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    
    using namespace std;
    
    typedef long long ll;
    
    const int N = 1000010;
    
    int n;
    
    struct Node
    {
        ll num;
        int pos;
        
        bool operator < (const Node &t) const
        {
            if(num == t.num) return pos > t.pos;
            return num < t.num;
        }
    }a[N];
    
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++) {
            ll x;
            scanf("%lld", &x);
            x -= 100;
            a[i].num = a[i - 1].num + x;
            a[i].pos = i;
        }
        a[0].num = 0, a[0].pos = 0;
        sort(a, a + n + 1);
        int ans = 0;
        int min_pos = n;
        for(int i = 0; i <= n; i ++) {
            if(a[i].pos > min_pos) ans = max(ans, a[i].pos - min_pos);
            min_pos = min(min_pos, a[i].pos);
        }
        printf("%d\n", ans);
        return 0;
    }
    
  • 相关阅读:
    延迟加载和缓存
    动态SQL
    Mybatis框架模糊查询+多条件查询
    mybatis增删改
    初始mybatis(二)
    Struts2框架和SpringMvc框架的区别
    MyBatis框架与Hibernate 框架的区别
    初始mybatis
    Servlet
    find命令使用
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/16415618.html
Copyright © 2020-2023  润新知