zoukankan      html  css  js  c++  java
  • bzoj3745 [COCI2015]Norma

    bzoj3745 [COCI2015]Norma

    给定正整数序列 (a_1, a_2, cdots, a_n) ,求 $$displaystylesum_{i=1}nsum_{j=i}n{(j-i+1)max[i, j]min [i, j]}$$

    将结果对 (10^9) 取模

    (nleq5 imes10^5, a_iin[0, 10^8])

    分治,cdq分治


    考虑分治,对于一个区间 ([l, r]) 找到 (max)(pos) ,向 ([l, pos-1], [pos+1, r]) 递归,但这样并不能有效处理 (min) 的贡献,于是考虑 cdq分治

    设当前区间为 ([l, r]) ,递归处理 ([l, mid], [mid+1, r]) ,并计算左端点在 ([l, mid]) ,右端点在 ([mid+1, r]) 的区间的贡献

    (mx=max[p, mid], mn=min[p, mid]) 。逆序枚举左端点 (p) ,令 (x) 为满足 (mngemin[mid+1, x]) 的最大的 (x)(y)(mxlemax[mid+1, y]) 的最大的 (y) 。假设 (x<y) ,右端点为 (q)

    1. (qleq x) 时,贡献为 (mx imes mn imesdisplaystylesum(q-p+1))
    2. (x<qleq y) 时,贡献为 (mx imes(displaystylesum((q-p+1) imesmin[x+1, q])))
    3. (y<q) 时,贡献为 (displaystylesum((q-p+1) imesmin[x+1, q] imesmax[y+1, q]))

    第一个可以直接算

    第二个可以将原式拆为 (mx imes(displaystylesum(q imesmin[x+1, q])-(i-1) imessummin[x+1, q])

    其中 (displaystylesummin[x+1, q])(displaystylesum(q imesmin[x+1, q])) 可以 (O(len)) 预处理

    第三个同样拆开括号,其中 (displaystylesum(min[x+1, q] imesmax[y+1, q]))(displaystylesum(q imesmin[x+1, q] imesmax[y+1, q])) 因为可以将 (min[x+1, q] imesmax[y+1, q]) 转化为 (min[x+1, q] imesmax[x+1, q]) ,同样可以 (O(len)) 预处理

    (xge y) 的情况同理

    时间复杂度 (O(nlog n))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int maxn = 5e5 + 10, P = 1e9, inf = 1e8;
    int n, ans, a[maxn], f1[maxn], f2[maxn], g1[maxn], g2[maxn], s1[maxn], s2[maxn];
    
    inline void chkmax(int &x, int y) {
      if (x < y) x = y;
    }
    
    inline void chkmin(int &x, int y) {
      if (x > y) x = y;
    }
    
    inline int inc(int x, int y) {
      x += y;
      return x < P ? x : x - P;
    }
    
    inline int dec(int x, int y) {
      x -= y;
      return x < 0 ? x + P : x;
    }
    
    inline int mul(int x, int y) {
      return 1ll * x * y % P;
    }
    
    inline int add(int &x, int y) {
      x += y;
      return x < P ? x : x -= P;
    }
    
    void cdq(int l, int r) {
      if (l == r) {
        add(ans, mul(a[l], a[l]));
        return;
      }
      int mid = (l + r) >> 1;
      cdq(l, mid), cdq(mid + 1, r);
      f1[mid] = f2[mid] = g1[mid] = g2[mid] = s1[mid] = s2[mid] = 0;
      for (int i = mid + 1, mx = 0, mn = inf; i <= r; i++) {
        chkmax(mx, a[i]), chkmin(mn, a[i]);
        f1[i] = inc(f1[i - 1], mx);
        g1[i] = inc(g1[i - 1], mn);
        f2[i] = inc(f2[i - 1], mul(mx, i));
        g2[i] = inc(g2[i - 1], mul(mn, i));
        s1[i] = inc(s1[i - 1], mul(mx, mn));
        s2[i] = inc(s2[i - 1], mul(mul(mx, mn), i));
      }
      for (int i = mid, mx = 0, mn = inf, x = mid, y = mid; i >= l; i--) {
        chkmax(mx, a[i]), chkmin(mn, a[i]);
        while (x < r && a[x] >= mn && a[x + 1] >= mn) x++;
        while (y < r && a[y] <= mx && a[y + 1] <= mx) y++;
        int p = min(x, y), q = max(x, y);
        add(ans, dec(dec(s2[r], s2[q]), mul(i - 1, dec(s1[r], s1[q]))));
        add(ans, mul(mul(mx, mn), dec(1ll * (p - mid) * (p + mid + 1) / 2 % P, mul(i - 1, p - mid))));
        if (x < y) {
          add(ans, mul(mx, dec(dec(g2[y], g2[x]), mul(i - 1, dec(g1[y], g1[x])))));
        } else {
          add(ans, mul(mn, dec(dec(f2[x], f2[y]), mul(i - 1, dec(f1[x], f1[y])))));
        }
      }
    }
    
    int main() {
      scanf("%d", &n);
      for (int i = 1; i <= n; i++) {
        scanf("%d", a + i);
      }
      cdq(1, n);
      printf("%d", ans);
      return 0;
    }
    
  • 相关阅读:
    Azure HPC Pack Cluster添加辅助节点
    Azure HPC Pack 辅助节点模板配置
    Azure HPC Pack配置管理系列(PART6)
    Windows HPC Pack 2012 R2配置
    Azure HPC Pack 节点提升成域控制器
    Azure HPC Pack VM 节点创建和配置
    Azure HPC Pack 部署必要条件准备
    Azure HPC Pack 基础拓扑概述
    Azure VM 性能计数器配置
    Maven私仓配置
  • 原文地址:https://www.cnblogs.com/Juanzhang/p/10990823.html
Copyright © 2011-2022 走看看