1 条题解

  • 0
    @ 2025-8-24 22:39:25

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Alex_Wei
    **

    搬运于2025-08-24 22:39:25,当前版本为作者最后更新于2022-08-21 12:50:23,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    C. P8476「GLR-R3」惊蛰

    考虑 DP,设 gi,jg_{i, j} 表示使得 bi=jb_i = j 的最小代价,则 $g_{i, j} = \min\limits_{k \geq j} g_{i - 1, k} + f(j, a_i)$。直接做时间复杂度 O(nV)\mathcal{O}(nV),不可接受。

    考虑转移的本质,对 gi1g_{i - 1} 做一遍后缀 min\min,然后令 gi,jgi1,j+f(j,ai)g_{i, j} \gets g_{i - 1, j} + f(j, a_i)ff 和后缀 min\min 的优秀性质使得可以快速维护 gg。具体地,对 gi1g_{i - 1} 做后缀 min\min 之后 gi1g_{i - 1} 具有单调性 gi1,jgi1,j+1g_{i - 1, j}\leq g_{i - 1, j + 1},而 f(j,ai)f(j, a_i) 是关于 jj 的分段函数,当 j<aij < a_i 时相当于为 gi1,jg_{i - 1, j} 区间加 CC,当 jaij \geq a_i 时相当于为 gi1,jg_{i - 1, j} 加上 jaij - a_i,两部分分别具有单调性,所以操作结束后 gi,jg_{i, j}aia_i 为分割线变成两段关于 jj 具有单调性的序列。

    根据上述分析,对 gi1g_{i - 1} 做后缀 min\min 时,只需线段树二分出 <ai1< a_{i - 1} 的位置中最后一个使得 gi,j>gi,ai1g_{i, j} > g_{i, a_{i - 1}} 的位置 jj,则该操作可视为对 gi1,jgi1,ai11g_{i - 1, j}\sim g_{i - 1, a_{i - 1} - 1} 区间赋值 gi1,ai1g_{i - 1, a_i - 1}

    aa 离散化,设 gi,jg_{i, j} 表示使得 bi=ajb_i = a_j 的最小代价,则需要支持以下操作:

    • 区间给位置 ii 加上 aia_i
    • 区间加法。
    • 区间赋值。
    • 线段树二分 <p< p 的位置最后一个 >v> v 的位置 qq,保证 <p< p 的位置具有单调性。

    维护区间最大值和赋值,加法,加 aia_i 懒标记即可。时间复杂度 O(nlogn)\mathcal{O}(n\log n)

    #include <bits/stdc++.h>
    using namespace std;
    using ll = long long;
    using pii = pair<int, int>;
    #define TIME 1e3 * clock() / CLOCKS_PER_SEC
    bool Mbe;
    constexpr int N = 1e6 + 5;
    ll val[N << 2], b[N];
    struct tag {
      ll ass, add, badd;
      tag operator + (const tag &x) const {
        if(x.ass != -1) return x;
        tag z = *this;
        z.add += x.add, z.badd += x.badd;
        return z;
      }
    } laz[N << 2];
    void eff(int l, ll x, tag v) {
      if(v.ass != -1) val[x] = v.ass;
      val[x] += v.add + b[l] * v.badd;
      laz[x] = laz[x] + v;
    }
    void down(int l, int r, int x) {
      int m = l + r >> 1;
      eff(m, x << 1, laz[x]);
      eff(r, x << 1 | 1, laz[x]);
      laz[x] = {-1, 0, 0};
    }
    void modify(int l, int r, int ql, int qr, int x, tag v) {
      if(ql > qr) return;
      if(ql <= l && r <= qr) return eff(r, x, v);
      int m = l + r >> 1;
      down(l, r, x);
      if(ql <= m) modify(l, m, ql, qr, x << 1, v);
      if(m < qr) modify(m + 1, r, ql, qr, x << 1 | 1, v);
      val[x] = max(val[x << 1], val[x << 1 | 1]);
    }
    int binary(int l, int r, int p, int x, ll lim) { // find the first position that val[x] >= lim
      if(r <= p && val[x] < lim) return -1;
      if(l == r) return l;
      int m = l + r >> 1;
      down(l, r, x);
      int res = binary(l, m, p, x << 1, lim);
      if(res != -1) return res;
      res = m < p ? binary(m + 1, r, p, x << 1 | 1, lim) : -1;
      return res;
    }
    ll query(int l, int r, int p, int x) {
      if(l == r) return val[x];
      int m = l + r >> 1;
      down(l, r, x);
      if(p <= m) return query(l, m, p, x << 1);
      return query(m + 1, r, p, x << 1 | 1);
    }
    int n, C, a[N];
    bool Med;
    int main() {
      fprintf(stderr, "%.3lf MB\n", (&Mbe - &Med) / 1048576.0);
      #ifdef ALEX_WEI
        freopen("1.in", "r", stdin);
        freopen("1.out", "w", stdout);
      #endif
      ios::sync_with_stdio(0);
      cin >> n >> C;
      for(int i = 1; i <= n; i++) cin >> a[i], b[i] = a[i];
      sort(b + 1, b + n + 1);
      for(int i = 1; i <= n << 2; i++) laz[i].ass = -1;
      for(int i = 1; i <= n; i++) {
        int p = lower_bound(b + 1, b + n + 1, a[i]) - b;
        modify(1, n, p + 1, n, 1, (tag) {-1, -a[i], 1});
        if(p == 1) continue;
        modify(1, n, 1, p - 1, 1, (tag) {-1, C, 0});
        ll v = query(1, n, p, 1);
        int pos = binary(1, n, p - 1, 1, v);
        if(pos != -1) modify(1, n, pos, p - 1, 1, (tag) {v, 0, 0});
      }
      cout << query(1, n, 1, 1) << "\n";
      cerr << TIME << " ms\n";
      return 0;
    }
    /*
    2022/8/14
    Author: Alex_Wei
    start coding at 15:55
    finish debugging at 16:40
    */
    
    • 1

    信息

    ID
    7473
    时间
    5000ms
    内存
    512MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者