• [HNOI2016]序列


    题面

    给你一个数列,很多组询问,每次询问 (l)(r) 的子区间的区间最小值之和。

    ( ext{Solution:})

    这种没有修改的,与子区间有关的题,不禁让我想起了影魔显然要离线做。

    先用单调栈预处理出每个点往左往右第一个比它小的位置 (L[i],R[i])

    (f[i]) 为以 (i) 结尾的区间最小值之和,

    显然有转移 : (f[i] = f[L[i]] + a[i] imes(i-L[i]))

    同理,(g[i]) 为以 (i) 开头的区间的最小值之和,

    (g[i] = g[R[i]] + a[i] imes (R[i] - i))

    考虑在莫队双指针移动的时候,计算区间内以右指针结尾的子区间的贡献,以及区间内以左指针开头的子区间的贡献,至于是 (+​) 还是 (-​) 贡献,由指针移动方向而定。

    这里举一个右指针右移的例子:

    ans += calcR(l, ++r);
    
    LL calcR(int l, int r) {
        int p = query(l, r);
        return a[p] * (p - l + 1) + f[r] - f[p];
    }
    

    这个函数就是计算以 (r+1) (没动之前为 (r) ) 结尾的子区间的贡献,(p) 为最小值的位置,显然 ([l,r],[l+1,r]dots [p,r]) 的子区间最小值都是 (a[p])([p+1,r]dots[r,r]) 的贡献就是 (f[r] - f[p])

    ({Source:})

    #include <set>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <assert.h>
    #include <algorithm>
    
    using namespace std;
    
    #define LL long long
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #define GO debug("GO
    ")
    
    inline int rint() {
      register int x = 0, f = 1; register char c;
      while (!isdigit(c = getchar())) if (c == '-') f = -1;
      while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getchar()));
      return x * f;
    }
    
    template<typename T> inline void chkmin(T &a, T b) { a > b ? a = b : 0; }
    template<typename T> inline void chkmax(T &a, T b) { a < b ? a = b : 0; }
    
    const int N = 1e5 + 10;
    
    #define pii pair<int, int>
    
    int n, m, a[N], L[N], R[N];
    LL f[N], g[N];
    struct Query {
      int l, r, id;
      bool operator< (const Query &b) const {
        return (l >> 8) == (b.l >> 8) ? r < b.r : l < b.l;
      }
    } q[N];
    
    namespace ST {
      pii st[N][22];
      void build() {
        for (int i = 1; i <= n; ++ i) st[i][0] = make_pair(a[i], i);
        for (int i = 1; n >> i; ++ i)
          for (int j = 1; j + (1 << i) - 1 <= n; ++ j)
            st[j][i] = min(st[j][i - 1], st[j + (1 << i - 1)][i - 1]);
      }
      int query(int l, int r) {
        int k = log2(r - l + 1);
        return min(st[l][k], st[r - (1 << k) + 1][k]).second;
      }
    }using ST::query;
    
    LL ans;
    
    LL calcR(int l, int r) {
      int p = query(l, r);
      return 1ll * (p - l + 1) * a[p] + f[r] - f[p];
    }
    
    LL calcL(int l, int r) {
      int p = query(l, r);
      return 1ll * (r - p + 1) * a[p] + g[l] - g[p];
    }
    LL res[N];
    int main() {
    #ifndef ONLINE_JUDGE
      freopen("xhc.in", "r", stdin);
      freopen("xhc.out", "w", stdout);
    #endif
      n = rint(), m = rint();
      for (int i = 1; i <= n; ++ i)
        a[i] = rint();
      for (int i = 1; i <= m; ++ i) {
        q[i].l = rint(), q[i].r = rint();
        q[i].id = i;
      }
    
      static int stk[N], top;
      top = 0;
      for (int i = 1; i <= n; ++ i) {
        while (top and a[stk[top]] > a[i]) 
          top --;
        L[i] = stk[top];
        stk[++top] = i;
      }
      stk[top = 0] = n + 1;
      for (int i = n; i >= 1; -- i) {
        while (top and a[stk[top]] > a[i])
          top --;
        R[i] = stk[top];
        stk[++top] = i;
      }
    
      for (int i = 1; i <= n; ++ i) 
        f[i] = f[L[i]] + 1ll * (i - L[i]) * a[i];
      for (int i = n; i >= 1; -- i)
        g[i] = g[R[i]] + 1ll * (R[i] - i) * a[i];
    
      ST::build();
    
      sort(q + 1, q + 1 + m);
      int l = 1, r = 0;
      for (int i = 1; i <= m; ++ i) {
        while (r < q[i].r) r++, ans += calcR(l, r);
        while (r > q[i].r) ans -= calcR(l, r), r--;
        while (l < q[i].l) ans -= calcL(l, r), l++;
        while (l > q[i].l) l--, ans += calcL(l, r);
        res[q[i].id] = ans;
      }
      for (int i = 1; i <= m; ++ i) printf("%lld
    ", res[i]);
    }
    
    
  • 相关阅读:
    一款React版本的excel插件(reactjexcel)
    如何评价微软的微服务构建框架Dapr?
    【优雅代码】深入浅出 妙用Javascript中apply、call、bind
    国内外最顶级的12大看板工具
    基于键盘钩子实现扫码枪输入
    中国有哪些比较出名的C#大佬。?
    一个数据驱动的高效 dotnet PDF 开源工具库
    Web前端:2022年最佳Javascript动画库
    分布式数据库的高可用性简史
    Vue项目首屏打开速度的优化
  • 原文地址:https://www.cnblogs.com/cnyali-Tea/p/10598016.html
Copyright © 2020-2023  润新知