Article Index

CSES 2425 Stack Weights 做题笔记

Published on

题意

有 $n$ 个砝码,编号为 $1$ 到 $n$。编号大的砝码一定比编号小的砝码重。

做 $n$ 操作,每次操作是把某个还没放在天平上的砝码放到天平的左边或者右边。问能否确定天平两边重量关系。

题解

定义 $l_i$ 为天平左边中,编号大于等于 $i$ 的砝码个数,$r_i$ 为天平右边中,编号大于等于 $i$ 的砝码个数。

左边比右边重,当且仅当对于所有 $1 \leq i \leq n$,满足 $l_i \geq r_i$。

原因很简单。若存在 $k$ 使得 $l_k < r_k$,则将编号小于 $k$ 的砝码 $i$ 的重量都定为 $i$,编号大于等于 $k$ 的砝码 $i$ 的重量都定为极大值加上 $i$ 即可使左边更轻。

用树状数组维护 $l_i - r_i$ 的值即可。

代码

struct SNOWFLAKE {
  using info = struct { int mn, mx; };

  static info sop(info a, info b) { return { std::min(a.mn, b.mn), std::max(a.mx, b.mx) }; }
  static info se() { return { INF32, -INF32 }; }
  static info smap(int f, info s) { return { s.mn + f, s.mx + f }; }
  static int scomp(int f1, int f2) { return f1 + f2; }
  static int sid() { return 0; }

  SNOWFLAKE([[maybe_unused]] int TEST_NUMBER) {
    int n; std::cin >> n;
    lib::Segtree<info, sop, se, int, smap, scomp, sid> o(n);
    for (int i = 0; i < n; ++i) o.set(i, { 0, 0 });
    for (int t = 0; t < n; ++t) {
      int a, x; std::cin >> a >> x;
      --a;
      if (x == 1) o.apply(0, a, 1);
      else o.apply(0, a, -1);
      if (o.all_prod().mn >= 0) std::cout << ">\n";
      else if (o.all_prod().mx <= 0) std::cout << "<\n";
      else std::cout << "?\n";
    }
  }
};

No comments

Post a comment