結果

問題 No.1226 I hate Robot Arms
ユーザー risujirohrisujiroh
提出日時 2020-09-11 22:19:28
言語 C++17
(gcc 13.2.0 + boost 1.83.0)
結果
AC  
実行時間 997 ms / 2,000 ms
コード長 6,175 bytes
コンパイル時間 5,109 ms
コンパイル使用メモリ 283,944 KB
実行使用メモリ 16,000 KB
最終ジャッジ日時 2023-08-30 09:59:19
合計ジャッジ時間 28,518 ms
ジャッジサーバーID
(参考情報)
judge15 / judge12
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,380 KB
testcase_01 AC 2 ms
4,384 KB
testcase_02 AC 282 ms
4,408 KB
testcase_03 AC 358 ms
5,960 KB
testcase_04 AC 396 ms
12,392 KB
testcase_05 AC 348 ms
14,848 KB
testcase_06 AC 962 ms
14,124 KB
testcase_07 AC 269 ms
4,932 KB
testcase_08 AC 88 ms
12,868 KB
testcase_09 AC 648 ms
5,692 KB
testcase_10 AC 72 ms
4,380 KB
testcase_11 AC 431 ms
11,884 KB
testcase_12 AC 235 ms
8,064 KB
testcase_13 AC 170 ms
15,096 KB
testcase_14 AC 796 ms
6,416 KB
testcase_15 AC 49 ms
13,644 KB
testcase_16 AC 932 ms
15,248 KB
testcase_17 AC 245 ms
6,800 KB
testcase_18 AC 162 ms
6,928 KB
testcase_19 AC 429 ms
13,356 KB
testcase_20 AC 417 ms
12,360 KB
testcase_21 AC 588 ms
11,288 KB
testcase_22 AC 951 ms
16,000 KB
testcase_23 AC 943 ms
15,772 KB
testcase_24 AC 971 ms
15,776 KB
testcase_25 AC 997 ms
15,876 KB
testcase_26 AC 976 ms
15,924 KB
testcase_27 AC 942 ms
15,896 KB
testcase_28 AC 937 ms
15,664 KB
testcase_29 AC 949 ms
15,892 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#pragma GCC optimize("Ofast")

#include <bits/extc++.h>

struct segment_tree_base {
  virtual int size() const = 0;

 protected:
  template <class F>
  void forward(int l, int r, F f) const {
    int h = h1(l += size() - 1, r += size());
    for (int s = 0; s < h; ++s)
      if (int i = l >> s; ~i & 1) f(i + 1);
    for (int s = h; s--;)
      if (int i = r >> s; i & 1) f(i - 1);
  }
  template <class F>
  void forward(int l, int r, F f) {
    const_cast<const segment_tree_base*>(this)->forward(l, r, f);
  }
  template <class F>
  void backward(int l, int r, F f) const {
    int h = h1(l += size() - 1, r += size());
    for (int s = 0; s < h; ++s)
      if (int i = r >> s; i & 1) f(i - 1);
    for (int s = h; s--;)
      if (int i = l >> s; ~i & 1) f(i + 1);
  }
  template <class F>
  void backward(int l, int r, F f) {
    const_cast<const segment_tree_base*>(this)->backward(l, r, f);
  }
  template <class F>
  void downward(int l, int r, F f) const {
    if (l == r or (l == 0 and r == size())) return;
    int h = h2(l += size(), r += size());
    for (int s = std::__lg(l); s > h; --s) f(l >> s);
    for (int s = h; s > __builtin_ctz(l); --s) f(l >> s);
    for (int s = h; s > __builtin_ctz(r); --s) f(r >> s);
  }
  template <class F>
  void downward(int l, int r, F f) {
    const_cast<const segment_tree_base*>(this)->downward(l, r, f);
  }
  template <class F>
  void upward(int l, int r, F f) const {
    if (l == r or (l == 0 and r == size())) return;
    int h = h2(l += size(), r += size());
    for (int s = __builtin_ctz(r); s++ < h;) f(r >> s);
    for (int s = __builtin_ctz(l); s++ < h;) f(l >> s);
    for (int s = h; s++ < std::__lg(l);) f(l >> s);
  }
  template <class F>
  void upward(int l, int r, F f) {
    const_cast<const segment_tree_base*>(this)->upward(l, r, f);
  }

 private:
  static int h1(int l, int r) {
    for (int h = 0;; ++h)
      if ((r >> h) - (l >> h) == 1) return h;
  }
  static int h2(int l, int r) {
    l <<= std::__lg(l) < std::__lg(r);
    return std::__lg(l ^ r);
  }
};

template <class T, class Action>
struct lazy_segment_tree : segment_tree_base {
  lazy_segment_tree() {}
  template <class Generator>
  lazy_segment_tree(int n, Generator gen) : tree(2 * n), lazy(n) {
    for (int i = 0; i < n; ++i) tree[n + i] = gen(i);
    for (int i = n; i-- > 1;) pull(i);
  }

  int size() const override { return std::size(lazy); }
  T fold(int l, int r) {
    assert(0 <= l), assert(l <= r), assert(r <= size());
    downward(l, r, [&](int i) { push(i); });
    T res{};
    forward(l, r, [&](int i) { res = res * tree[i]; });
    return res;
  }
  T get(int i) {
    assert(0 <= i), assert(i < size());
    return fold(i, i + 1);
  }
  T fold_all_rotated() const { return size() ? tree[1] : T{}; }
  template <class Function>
  void update(int i, Function func) {
    assert(0 <= i), assert(i < size());
    downward(i, i + 1, [&](int j) { push(j); });
    tree[size() + i] = func(tree[size() + i]);
    upward(i, i + 1, [&](int j) { pull(j); });
  }
  void act(int l, int r, const Action& f) {
    assert(0 <= l), assert(l <= r), assert(r <= size());
    downward(l, r, [&](int i) { push(i); });
    forward(l, r, [&](int i) { apply(i, f); });
    upward(l, r, [&](int i) { pull(i); });
  }
  template <class Predicate>
  int forward_search(int l, int r, Predicate pred) {
    assert(0 <= l), assert(l <= r), assert(r <= size());
    downward(l, r, [&](int i) { push(i); });
    T a{};
    assert(pred(a));
    int res = r;
    forward(l, r, [&](int i) {
      if (res < r) return;
      if (T na = a * tree[i]; pred(na)) {
        a = na;
        return;
      }
      while (i < size()) {
        push(i);
        if (T na = a * tree[i *= 2]; pred(na)) a = na, ++i;
      }
      res = i - size();
    });
    return res;
  }
  template <class Predicate>
  int backward_search(int l, int r, Predicate pred) {
    assert(0 <= l), assert(l <= r), assert(r <= size());
    downward(l, r, [&](int i) { push(i); });
    T a{};
    assert(pred(a));
    int res = l - 1;
    backward(l, r, [&](int i) {
      if (res >= l) return;
      if (T na = a * tree[i]; pred(na)) {
        a = na;
        return;
      }
      while (i < size()) {
        push(i);
        if (T na = a * tree[i = 2 * i + 1]; pred(na)) a = na, --i;
      }
      res = i - size();
    });
    return res;
  }

 private:
  std::vector<T> tree;
  std::vector<Action> lazy;

  void apply(int i, const Action& f) {
    tree[i] = f(tree[i]);
    if (i < size()) lazy[i] = lazy[i] * f;
  }
  void push(int i) {
    apply(2 * i, lazy[i]), apply(2 * i + 1, lazy[i]);
    lazy[i] = Action{};
  }
  void pull(int i) { tree[i] = tree[2 * i] * tree[2 * i + 1]; }
};

using num = std::complex<long double>;

struct node {
  num z;
  friend node operator*(const node& a, const node& b) { return {a.z + b.z}; }
};
struct action {
  num a = 1, b;
  node operator()(const node& x) const { return {x.z * a + b}; }
  friend action operator*(const action& f, const action& g) {
    return {f.a * g.a, f.b * g.a + g.b};
  }
};

int main() {
  using namespace std;
  cin.tie(nullptr)->sync_with_stdio(false);
  cout << fixed << setprecision(10);

  int n, q;
  cin >> n >> q;

  lazy_segment_tree<node, action> seg(n, [](int i) -> node { return {i + 1}; });
  auto get_len = [&](int i) {
    num d = seg.get(i).z - (i ? seg.get(i - 1).z : 0);
    return abs(d);
  };
  auto get_arg = [&](int i) -> num::value_type {
    if (i == -1) return 0;
    num d = seg.get(i).z - (i ? seg.get(i - 1).z : 0);
    return arg(d);
  };

  while (q--) {
    int t, i;
    cin >> t >> i;
    --i;
    if (t == 0) {
      num::value_type x;
      cin >> x;
      x /= 180;
      x *= acos(num::value_type(-1));
      num off = i ? seg.get(i - 1).z : 0;
      auto th = get_arg(i - 1) + x - get_arg(i);
      seg.act(i, n, {1, -off});
      seg.act(i, n, {polar(num::value_type(1), th), 0});
      seg.act(i, n, {1, +off});
    } else if (t == 1) {
      int x;
      cin >> x;
      seg.act(i, n, {1, polar(x - get_len(i), get_arg(i))});
    } else if (t == 2) {
      auto z = seg.get(i).z;
      cout << real(z) << ' ' << imag(z) << '\n';
    } else
      assert(false);
  }
}
0