zoukankan      html  css  js  c++  java
  • D. Yet Another Yet Another Task (ST表模版 + 单调队列)

    题目链接:https://codeforces.com/contest/1359/problem/D

    想法:

    因为是减去最大值,我们可以考虑直接枚举最大值。

    找到左边最后一个 小于等于a[i] 的位置,找到右边最后一个 小于等于a[i] 的位置

    找到这样的一个子区间,然后我们利用ST表维护前缀和,找到左边前缀和最小,右边前缀和最大的这样的范围就好了。

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #include <algorithm>
    #include <string>
    #include <cstring>
    #include <vector>
    #include <map>
    #include <stack>
    #include <set>
    #include <queue>
    #include <cmath>
    #include <cstdio>
    #include <iomanip>
    #include <ctime>
    #include <bitset>
    #include <cmath>
    #include <sstream>
    #include <iostream>
    
    #define ll long long
    #define ls nod<<1
    #define rs (nod<<1)+1
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define INF 0x3f3f3f3f3f3f3f3f
    #define max(a, b) (a>b?a:b)
    #define min(a, b) (a<b?a:b)
    
    
    const double eps = 1e-10;
    const int maxn = 2e5 + 10;
    const int MOD = 998244353;
    
    int sgn(double a) { return a < -eps ? -1 : a < eps ? 0 : 1; }
    
    using namespace std;
    
    
    int a[maxn];
    int q[maxn];
    int f1[maxn],f2[maxn];
    
    
    int pre[maxn],maxx[maxn][20],minn[maxn][20];
    void rmq(int n)
    {
        for(int i=0;i<=n;i++) minn[i][0]=maxx[i][0]=pre[i];
        for(int j=1;(1<<j)<=n;j++)
        {
            for(int i=0;i+j-1<=n;i++)
            {
                maxx[i][j]=max(maxx[i][j-1],maxx[i+(1<<(j-1))][j-1]);
                minn[i][j]=min(minn[i][j-1],minn[i+(1<<(j-1))][j-1]);
            }
        }
    }
    int q1(int l,int r)
    {
        int k=0,dis=r-l+1;
        while((1<<(k+1))<=dis) ++k;
        return max(maxx[l][k],maxx[r-(1<<k)+1][k]);
    }
    int q2(int l,int r)
    {
        int k=0,dis=r-l+1;
        while((1<<(k+1))<=dis) ++k;
        return min(minn[l][k],minn[r-(1<<k)+1][k]);
    }
    
    
    int main() {
        int n;
        scanf("%d",&n);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            pre[i] = pre[i-1] + a[i];
        }
        rmq(n);
        int cnt;
    
        // 右边第一个 > a[i] 的数的位置
        q[1] = n + 1;
        cnt = 1;
        a[n + 1] = INF;
        for (int i = n; i >= 1; i--) {
            while (cnt && a[q[cnt]] <= a[i])
                cnt--;
            f1[i] = q[cnt] - 1;
            q[++cnt] = i;
        }
        // 左边第一个 > a[i] 的数的位置
        q[1] = 0;
        cnt = 1;
        a[0] = INF;
        for (int i = 1;i <= n;i++) {
            while (cnt && a[q[cnt]] <= a[i])
                cnt--;
            f2[i] = q[cnt];
            q[++cnt] = i;
        }
    //    for (int i = 1;i <= n;i++) {
    //        cout << f2[i] << " ";
    //    }
    //    cout << endl;
        int ans = 0;
        for (int i = 1;i <= n;i++) {
            int l = f2[i],r = f1[i];
            int maxl = q2(l,i-1);
            int maxr = q1(i,r);
            ans = max(ans,maxr - maxl - a[i]);
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Codeforces 1291 Round #616 (Div. 2) B
    总结
    刷新DNS解析缓存+追踪+域名解析命令
    数学--数论--Hdu 5793 A Boring Question (打表+逆元)
    Lucene.net(4.8.0) 学习问题记录六:Lucene 的索引系统和搜索过程分析
    LeetCode 117 Populating Next Right Pointers in Each Node II
    LeetCode 116 Populating Next Right Pointers in Each Node
    test test
    LeetCode 115 Distinct Subsequences
    LeetCode 114. Flatten Binary Tree to Linked List
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/13200363.html
Copyright © 2011-2022 走看看