zoukankan      html  css  js  c++  java
  • 2019牛客多校第四场C-sequence(单调栈+线段树)

    sequence

    题目传送门

    解题思路

    用单调栈求出每个a[i]作为最小值的最大范围。对于每个a[i],我们都要乘以一个以a[i]为区间内最小值的对应的b的区间和s,如果a[i] > 0,则s要尽量大,如果a[i] < 0,则s要尽量小。因为一段区间的和可以利用前缀和c[]相减求出,而以a[i]为最小值的区间和为:c[i~r] - c[l-1~i-1]。 所以用b[i]的前缀和建立线段树,维护其最大最小值。要求最大的s,即为求ir内的最大前缀和与l-1i-1范围内的最小前缀和。求最小的s同理。

    代码如下

    #include <bits/stdc++.h>
    #define INF 5223372036854775807LL
    using namespace std;
    typedef long long ll;
    
    inline int read(){
        int res = 0, w = 0; char ch = 0;
        while(!isdigit(ch)){
            w |= ch == '-', ch = getchar();
        }
        while(isdigit(ch)){
            res = (res << 3) + (res << 1) + (ch ^ 48);
            ch = getchar();
        }
        return w ? -res : res;
    }
    
    const int N = 3000005;
    
    ll a[N], b[N];
    ll c[N];
    struct T{
        int l, r;
        ll maxx, minn;
    }tree[N<<2];
    
    void build(int k, int l, int r)
    {
        tree[k].l = l;
        tree[k].r = r;
        if(l == r){
            tree[k].maxx = tree[k].minn = c[l];
            return;
        }
        int mid = (l + r) / 2;
        build(2*k, l, mid);
        build(2*k+1, mid + 1, r);
        tree[k].maxx = max(tree[2*k].maxx, tree[2*k+1].maxx);
        tree[k].minn = min(tree[2*k].minn, tree[2*k+1].minn);
    }
    
    ll query_minn(int k, int l, int r)
    {
        if(tree[k].l >= l && tree[k].r <= r)
            return tree[k].minn;
        int mid = (tree[k].l + tree[k].r) / 2;
        ll m1 = INF, m2 = INF;
        if(l <= mid)
            m1 = query_minn(2*k, l, r);
        if(r > mid)
            m2 = query_minn(2*k+1, l, r);
        return min(m1, m2);
    }
    
    ll query_maxx(int k, int l, int r)
    {
        if(tree[k].l >= l && tree[k].r <= r)
            return tree[k].maxx;
        int mid = (tree[k].l + tree[k].r) / 2;
        ll m1 = -INF, m2 = -INF;
        if(l <= mid)
            m1 = query_maxx(2*k, l, r);
        if(r > mid)
            m2 = query_maxx(2*k+1, l, r);
        return max(m1, m2);
    }
    
    int l[N], r[N];
    int dq[N];
    
    int main()
    {
        int n;
        n = read();
        for(int i = 1; i <= n; i ++)
            a[i] = read();
        for(int i = 1; i <= n; i ++)
            b[i] = read();
        for(int i = 1; i <= n; i ++)
            c[i] = c[i - 1] + b[i];
        build(1, 1, n);
        int ql, qr;
        ql = qr = 0;
        for(int i = 1; i <= n; i ++){
            while(ql != qr && a[dq[qr - 1]] >= a[i])
                qr --;
            if(ql != qr)
                l[i] = dq[qr - 1] + 1;
            else
                l[i] = 1;
            dq[qr++] = i;
        }
        ql = qr = 0;
        for(int i = n; i >= 1; i --){
            while(ql != qr && a[dq[qr - 1]] >= a[i])
                qr --;
            if(ql != qr)
                r[i] = dq[qr - 1] - 1;
            else
                r[i] = n;
            dq[qr++] = i;
        }
        ll ans = -INF;
        for(int i = 1; i <= n; i ++){
            if(a[i] < 0){
                ans = max(ans, a[i] * (query_minn(1, i, r[i]) - query_maxx(1, l[i] - 1, i - 1)));
            }
            else if(a[i] > 0){
                ans = max(ans, a[i] * (query_maxx(1, i, r[i]) - query_minn(1, l[i] - 1, i - 1)));
            }
            else
                ans = max(ans, 0LL);
        }
        cout << ans << endl;
        return 0;
    }
    
  • 相关阅读:
    lazyload【思路】
    图片旋转
    模拟滚动条【大体功能实现】
    Firefox window.close()的使用注意事项
    修改KindEditor的CSS文件
    ownerDocument property
    网易新闻图片展示效果
    关于td不支持position问题
    strcat strncat
    Tcl_FindExecutable
  • 原文地址:https://www.cnblogs.com/whisperlzw/p/11262756.html
Copyright © 2011-2022 走看看