結果

問題 No.3675 偏光板
コンテスト
ユーザー maspy
提出日時 2026-09-05 01:24:53
言語 C++23
(gcc 15.3.0 + boost 1.92.0)
コンパイル:
g++-15 -O2 -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
WA  
実行時間 -
コード長 25,500 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 4,698 ms
コンパイル使用メモリ 392,884 KB
実行使用メモリ 6,400 KB
最終ジャッジ日時 2026-09-05 01:25:08
合計ジャッジ時間 12,213 ms
ジャッジサーバーID
(参考情報)
judge3_0 / judge1_0
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 6
other AC * 52 WA * 2
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

// BEGIN: main.cpp
#line 1 "main.cpp"
// BEGIN: my_template.hpp
#line 1 "my_template.hpp"
#if defined(USE_PCH)
#include <my_template_compiled.hpp>
#else
#if defined(__GNUC__)
#include <bits/allocator.h>
#pragma GCC optimize("Ofast,unroll-loops")
// 環境によってはコンパイル成功かつ実行時エラー
#pragma GCC target("avx2,popcnt")
#endif
#include <bits/stdc++.h>
#include <cassert>

using namespace std;

using ll = long long;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
using i128 = __int128;
using u128 = unsigned __int128;
using f128 = __float128;

template <class>
constexpr bool dependent_false = false;

template <class T>
constexpr T infty = [] {
  static_assert(dependent_false<T>, "infty<T> is not defined");
  return T{};
}();
template <>
constexpr int infty<int> = 1'010'000'000;
template <>
constexpr ll infty<ll> = 2'020'000'000'000'000'000;
template <>
constexpr u32 infty<u32> = infty<int>;
template <>
constexpr u64 infty<u64> = infty<ll>;
template <>
constexpr i128 infty<i128> = i128(infty<ll>) * 2'000'000'000'000'000'000;
template <>
constexpr double infty<double> = infty<i128>;
template <>
constexpr long double infty<long double> = infty<i128>;

using pi = pair<ll, ll>;
using vi = vector<ll>;
template <class T>
using vc = vector<T>;
template <class T>
using vvc = vector<vc<T>>;
template <class T>
using vvvc = vector<vvc<T>>;
template <class T>
using vvvvc = vector<vvvc<T>>;
template <class T>
using pq_max = priority_queue<T>;
template <class T>
using pq_min = priority_queue<T, vector<T>, greater<T>>;

#define vv(type, name, h, ...) \
  vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define vvv(type, name, h, w, ...)   \
  vector<vector<vector<type>>> name( \
      h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)       \
  vector<vector<vector<vector<type>>>> name( \
      a, vector<vector<vector<type>>>(       \
             b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))

// https://trap.jp/post/1224/
#define FOR1(a) for (ll _ = 0; _ < ll(a); ++_)
#define FOR2(i, a) for (ll i = 0; i < ll(a); ++i)
#define FOR3(i, a, b) for (ll i = a; i < ll(b); ++i)
#define FOR4(i, a, b, c) for (ll i = a; i < ll(b); i += (c))
#define FOR1_R(a) for (ll i = ll(a) - 1; i >= ll(0); --i)
#define FOR2_R(i, a) for (ll i = ll(a) - 1; i >= ll(0); --i)
#define FOR3_R(i, a, b) for (ll i = ll(b) - 1; i >= ll(a); --i)
#define overload4(a, b, c, d, e, ...) e
#define overload3(a, b, c, d, ...) d
#define FOR(...) overload4(__VA_ARGS__, FOR4, FOR3, FOR2, FOR1)(__VA_ARGS__)
#define FOR_R(...) overload3(__VA_ARGS__, FOR3_R, FOR2_R, FOR1_R)(__VA_ARGS__)

#define all(x) (x).begin(), (x).end()
#define len(x) ll(x.size())
#define elif else if

#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second

#define stoi stoll

// require y > 0
template <typename T>
T floor(T x, T y) {
  return x / y - (x % y < 0);
}

// require y > 0
template <typename T>
T ceil(T x, T y) {
  return (x / y) + (x % y > 0);
}

// require y > 0
template <typename T>
T bmod(T x, T y) {
  T r = x % y;
  return (r < 0 ? r + y : r);
}

// require y > 0
template <typename T>
pair<T, T> divmod(T x, T y) {
  T q = x / y, r = x % y;
  if (r < 0) --q, r += y;
  return {q, r};
}

constexpr auto TEN = [] {
  array<u64, 20> A{};
  A[0] = 1;
  for (int i = 1; i < 20; ++i) A[i] = 10 * A[i - 1];
  return A;
}();

template <typename T, typename U>
T SUM(const U &A) {
  return std::accumulate(A.begin(), A.end(), T{});
}

#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
template <class C, class T>
inline long long LB(const C &c, const T &x) {
  return lower_bound(c.begin(), c.end(), x) - c.begin();
}
template <class C, class T>
inline long long UB(const C &c, const T &x) {
  return upper_bound(c.begin(), c.end(), x) - c.begin();
}
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())

template <typename T>
T POP(deque<T> &que) {
  T a = que.front();
  que.pop_front();
  return a;
}
template <class T, class Container, class Compare>
T POP(priority_queue<T, Container, Compare> &que) {
  T a = que.top();
  que.pop();
  return a;
}
template <typename T>
T POP(vc<T> &que) {
  T a = que.back();
  que.pop_back();
  return a;
}

template <typename F>
i128 binary_search(F check, i128 ok, i128 ng, bool check_ok = true) {
  if (check_ok) assert(check(ok));
  while (1) {
    i128 x = (ok + ng) / 2;
    if (x == ok || x == ng) break;
    (check(x) ? ok : ng) = x;
  }
  return ok;
}

template <typename F>
double binary_search_real(F check, double ok, double ng, int iter = 100) {
  FOR(iter) {
    double x = (ok + ng) / 2;
    (check(x) ? ok : ng) = x;
  }
  return (ok + ng) / 2;
}

template <class T, class S>
inline bool chmax(T &a, const S &b) {
  T c = max<T>(a, b);
  bool changed = (c != a);
  a = c;
  return changed;
}
template <class T, class S>
inline bool chmin(T &a, const S &b) {
  T c = min<T>(a, b);
  bool changed = (c != a);
  a = c;
  return changed;
}

// ? は -1
vc<int> s_to_vi(const string &S, char first_char) {
  vc<int> A(S.size());
  FOR(i, S.size()) { A[i] = (S[i] != '?' ? S[i] - first_char : -1); }
  return A;
}

template <typename T, typename U>
vc<T> cumsum(const vc<U> &A, int off = 1) {
  int N = A.size();
  vc<T> B(N + 1);
  FOR(i, N) { B[i + 1] = B[i] + A[i]; }
  if (off == 0) B.erase(B.begin());
  return B;
}

// stable sort
template <typename T>
vc<int> argsort(const vc<T> &A) {
  vc<int> ids(len(A));
  iota(all(ids), 0);
  sort(all(ids),
      [&](int i, int j) { return (A[i] == A[j] ? i < j : A[i] < A[j]); });
  return ids;
}

// A[I[0]], A[I[1]], ...
template <typename T>
vc<T> rearrange(const vc<T> &A, const vc<int> &I) {
  vc<T> B(len(I));
  FOR(i, len(I)) B[i] = A[I[i]];
  return B;
}

template <typename T, typename... Vectors>
void concat(vc<T> &first, const Vectors &...others) {
  first.reserve(first.size() + (others.size() + ... + 0));
  (first.insert(first.end(), others.begin(), others.end()), ...);
}

// i128
template <class T, enable_if_t<is_same_v<T, i128>, int> = 0>
constexpr i128 abs(T x) {
  return x < 0 ? -x : x;
}

constexpr i128 gcd(i128 a, i128 b) {
  while (b != 0) {
    i128 c = a % b;
    a = b, b = c;
  }
  return abs(a);
}
#endif
// END: my_template.hpp
#line 2 "main.cpp"
// BEGIN: other/io.hpp
#line 1 "other/io.hpp"
#define FASTIO

// https://judge.yosupo.jp/submission/21623
namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf
uint32_t pil = 0, pir = 0, por = 0;
bool input_eof = false;

template <class T>
constexpr bool is_signed_integer_v = is_signed_v<T> || is_same_v<T, i128>;

template <class T>
struct unsigned_integer {
  using type = make_unsigned_t<T>;
};
template <>
struct unsigned_integer<i128> {
  using type = u128;
};
template <>
struct unsigned_integer<u128> {
  using type = u128;
};
template <class T>
using unsigned_integer_t = typename unsigned_integer<T>::type;

[[noreturn]] inline void input_error(const char *message) {
  fputs(message, stderr);
  fputc('\n', stderr);
  exit(EXIT_FAILURE);
}

struct Pre {
  char num[10000][4];
  constexpr Pre() : num() {
    for (int i = 0; i < 10000; i++) {
      int n = i;
      for (int j = 3; j >= 0; j--) {
        num[i][j] = n % 10 | '0';
        n /= 10;
      }
    }
  }
} constexpr pre;

inline void load() {
  uint32_t n = pir - pil;
  memmove(ibuf, ibuf + pil, n);
  pil = 0;
  pir = n;
  if (input_eof) return;

  pir += fread(ibuf + pir, 1, SZ - pir, stdin);
  if (ferror(stdin)) input_error("fastio: input error");
  if (feof(stdin)) {
    input_eof = true;
    // Allows the last token to end exactly at EOF without a trailing
    // whitespace.
    if (pir < SZ) ibuf[pir++] = '\n';
  }
}

inline char get_char() {
  if (pil == pir) {
    load();
    if (pil == pir) input_error("fastio: unexpected EOF");
  }
  return ibuf[pil++];
}

inline void flush() {
  fwrite(obuf, 1, por, stdout);
  por = 0;
}

void rd(char &c) {
  do c = get_char();
  while (isspace(static_cast<unsigned char>(c)));
}

void rd(string &x) {
  x.clear();
  char c;
  do c = get_char();
  while (isspace(static_cast<unsigned char>(c)));
  do {
    x += c;
    c = get_char();
  } while (!isspace(static_cast<unsigned char>(c)));
}

template <typename T>
void rd_real(T &x) {
  string s;
  rd(s);
  x = stod(s);
}

template <typename T>
void rd_integer_slow(T &x) {
  char c;
  do c = get_char();
  while (c < '-');
  bool minus = 0;
  if constexpr (is_signed_integer_v<T>) {
    if (c == '-') {
      minus = 1, c = get_char();
    }
  }
  x = 0;
  assert('0' <= c && c <= '9');
  while ('0' <= c && c <= '9') {
    x = x * 10 + (c & 15), c = get_char();
  }
  assert(isspace(static_cast<unsigned char>(c)));
  if constexpr (is_signed_integer_v<T>) {
    if (minus) x = -x;
  }
}

template <typename T>
void rd_integer(T &x) {
  if (pil + 100 > pir) {
    load();
    if (pil + 100 > pir) {
      rd_integer_slow(x);
      return;
    }
  }
  char c;
  do c = ibuf[pil++];
  while (c < '-');
  bool minus = 0;
  if constexpr (is_signed_integer_v<T>) {
    if (c == '-') {
      minus = 1, c = ibuf[pil++];
    }
  }
  x = 0;
  assert('0' <= c && c <= '9');
  while ('0' <= c && c <= '9') {
    x = x * 10 + (c & 15), c = ibuf[pil++];
  }
  assert(isspace(static_cast<unsigned char>(c)));
  if constexpr (is_signed_integer_v<T>) {
    if (minus) x = -x;
  }
}

template <class T>
enable_if_t<is_integral_v<T> || is_same_v<T, i128> || is_same_v<T, u128>> rd(
    T &x) {
  rd_integer(x);
}

template <class T>
enable_if_t<is_floating_point_v<T> || is_same_v<T, f128>> rd(T &x) {
  rd_real(x);
}

template <class T, class U>
void rd(pair<T, U> &p) {
  rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T>
void rd_tuple(T &t) {
  if constexpr (N < tuple_size<T>::value) {
    auto &x = get<N>(t);
    rd(x);
    rd_tuple<N + 1>(t);
  }
}
template <class... T>
void rd(tuple<T...> &tpl) {
  rd_tuple(tpl);
}

template <class T, size_t N>
void rd(array<T, N> &x) {
  for (auto &d : x) rd(d);
}
template <class T>
void rd(vc<T> &x) {
  for (auto &d : x) rd(d);
}

template <class... T>
void read(T &...x) {
  (rd(x), ...);
}

inline void wt_range(const char *s, size_t n) {
  size_t i = 0;
  while (i < n) {
    if (por == SZ) flush();
    size_t chunk = min(n - i, (size_t)(SZ - por));
    memcpy(obuf + por, s + i, chunk);
    por += chunk;
    i += chunk;
  }
}

void wt(const char c) {
  if (por == SZ) flush();
  obuf[por++] = c;
}
void wt(const char *s) { wt_range(s, strlen(s)); }
void wt(const string &s) { wt_range(s.data(), s.size()); }

template <typename T>
void wt_integer(T x) {
  if (por > SZ - 100) flush();
  using U = unsigned_integer_t<T>;
  U y = static_cast<U>(x);
  if constexpr (is_signed_integer_v<T>) {
    if (x < 0) {
      obuf[por++] = '-';
      y = U(0) - y;
    }
  }
  int outi;
  for (outi = 96; y >= 10000; outi -= 4) {
    memcpy(out + outi, pre.num[y % 10000], 4);
    y /= 10000;
  }
  if (y >= 1000) {
    memcpy(obuf + por, pre.num[y], 4);
    por += 4;
  } else if (y >= 100) {
    memcpy(obuf + por, pre.num[y] + 1, 3);
    por += 3;
  } else if (y >= 10) {
    int q = (y * 103) >> 10;
    obuf[por] = q | '0';
    obuf[por + 1] = (y - q * 10) | '0';
    por += 2;
  } else
    obuf[por++] = y | '0';
  memcpy(obuf + por, out + outi + 4, 96 - outi);
  por += 96 - outi;
}

template <typename T>
inline void wt_real(T x) {
  static char buf[1000];
  int n = std::snprintf(buf, sizeof(buf), "%.15f", (double)x);
  wt_range(buf, (size_t)n);
}

template <class T>
enable_if_t<is_integral_v<T> || is_same_v<T, i128> || is_same_v<T, u128>> wt(
    T x) {
  wt_integer(x);
}

template <class T>
enable_if_t<is_floating_point_v<T> || is_same_v<T, f128>> wt(T x) {
  wt_real(x);
}

inline void wt(bool b) { wt(static_cast<char>('0' + (b ? 1 : 0))); }

template <class T, class U>
void wt(const pair<T, U> &val) {
  wt(val.first);
  wt(' ');
  wt(val.second);
}
template <size_t N = 0, typename T>
void wt_tuple(const T &t) {
  if constexpr (N < tuple_size<T>::value) {
    if constexpr (N > 0) wt(' ');
    wt(get<N>(t));
    wt_tuple<N + 1>(t);
  }
}
template <class... T>
void wt(const tuple<T...> &tpl) {
  wt_tuple(tpl);
}
template <class T, size_t S>
void wt(const array<T, S> &val) {
  auto n = val.size();
  for (size_t i = 0; i < n; i++) {
    if (i) wt(' ');
    wt(val[i]);
  }
}
template <class T>
void wt(const vector<T> &val) {
  auto n = val.size();
  for (size_t i = 0; i < n; i++) {
    if (i) wt(' ');
    wt(val[i]);
  }
}

void print() { wt('\n'); }
template <class Head, class... Tail>
void print(Head &&head, Tail &&...tail) {
  wt(forward<Head>(head));
  ((wt(' '), wt(forward<Tail>(tail))), ...);
  wt('\n');
}

// gcc expansion. called automaticall after main.
void __attribute__((destructor)) _d() { flush(); }
}  // namespace fastio
using fastio::flush;
using fastio::print;
using fastio::read;

#if defined(LOCAL)
#define HDR "[DEBUG:", __func__, __LINE__, "]"
#define SHOW(...)                                                         \
  SHOW_IMPL(__VA_ARGS__, SHOW8, SHOW7, SHOW6, SHOW5, SHOW4, SHOW3, SHOW2, \
            SHOW1)                                                        \
  (__VA_ARGS__)
#define SHOW_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, NAME, ...) NAME
#define SHOW1(x) print(HDR, #x, "=", (x)), flush()
#define SHOW2(x, y) print(HDR, #x, "=", (x), #y, "=", (y)), flush()
#define SHOW3(x, y, z) \
  print(HDR, #x, "=", (x), #y, "=", (y), #z, "=", (z)), flush()
#define SHOW4(x, y, z, w) \
  print(HDR, #x, "=", (x), #y, "=", (y), #z, "=", (z), #w, "=", (w)), flush()
#define SHOW5(x, y, z, w, v)                                                  \
  print(HDR, #x, "=", (x), #y, "=", (y), #z, "=", (z), #w, "=", (w), #v, "=", \
        (v)),                                                                 \
      flush()
#define SHOW6(x, y, z, w, v, u)                                               \
  print(HDR, #x, "=", (x), #y, "=", (y), #z, "=", (z), #w, "=", (w), #v, "=", \
        (v), #u, "=", (u)),                                                   \
      flush()
#define SHOW7(x, y, z, w, v, u, t)                                            \
  print(HDR, #x, "=", (x), #y, "=", (y), #z, "=", (z), #w, "=", (w), #v, "=", \
        (v), #u, "=", (u), #t, "=", (t)),                                     \
      flush()
#define SHOW8(x, y, z, w, v, u, t, s)                                         \
  print(HDR, #x, "=", (x), #y, "=", (y), #z, "=", (z), #w, "=", (w), #v, "=", \
        (v), #u, "=", (u), #t, "=", (t), #s, "=", (s)),                       \
      flush()
#else
#define SHOW(...)
#endif

#define INT(...)   \
  int __VA_ARGS__; \
  read(__VA_ARGS__)
#define LL(...)   \
  ll __VA_ARGS__; \
  read(__VA_ARGS__)
#define U32(...)   \
  u32 __VA_ARGS__; \
  read(__VA_ARGS__)
#define U64(...)   \
  u64 __VA_ARGS__; \
  read(__VA_ARGS__)
#define STR(...)      \
  string __VA_ARGS__; \
  read(__VA_ARGS__)
#define CHAR(...)   \
  char __VA_ARGS__; \
  read(__VA_ARGS__)
#define DBL(...)      \
  double __VA_ARGS__; \
  read(__VA_ARGS__)

#define VEC(type, name, size) \
  vector<type> name(size);    \
  read(name)
#define VV(type, name, h, w)                     \
  vector<vector<type>> name(h, vector<type>(w)); \
  read(name)

void YES(bool t = 1) { print(t ? "YES" : "NO"); }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { print(t ? "Yes" : "No"); }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { print(t ? "yes" : "no"); }
void no(bool t = 1) { yes(!t); }
void YA(bool t = 1) { print(t ? "YA" : "TIDAK"); }
void TIDAK(bool t = 1) { YA(!t); }
void Alice(bool t = 1) { print(t ? "Alice" : "Bob"); }
void Bob(bool t = 1) { Alice(!t); }// END: other/io.hpp
#line 3 "main.cpp"

// BEGIN: geo/base.hpp
#line 1 "geo/base.hpp"
template <typename T>
struct Point {
  T x, y;

  Point() : x(0), y(0) {}

  template <typename A, typename B>
  Point(A x, B y) : x(x), y(y) {}

  template <typename A, typename B>
  Point(pair<A, B> p) : x(p.fi), y(p.se) {}

  template <typename U>
  Point(Point<U> p) : x(p.x), y(p.y) {
    static_assert(!is_integral_v<T> || is_integral_v<U>);
  }

  Point operator+=(const Point p) {
    x += p.x, y += p.y;
    return *this;
  }
  Point operator-=(const Point p) {
    x -= p.x, y -= p.y;
    return *this;
  }
  Point operator+(Point p) const { return {x + p.x, y + p.y}; }
  Point operator-(Point p) const { return {x - p.x, y - p.y}; }
  bool operator==(Point p) const { return x == p.x && y == p.y; }
  bool operator!=(Point p) const { return x != p.x || y != p.y; }
  Point operator-() const { return {-x, -y}; }
  Point operator*(T t) const { return {x * t, y * t}; }
  Point operator/(T t) const { return {x / t, y / t}; }

  bool operator<(Point p) const {
    if (x != p.x) return x < p.x;
    return y < p.y;
  }
  T dot(const Point& other) const { return x * other.x + y * other.y; }
  T det(const Point& other) const { return x * other.y - y * other.x; }

  double norm() { return sqrtl(x * x + y * y); }
  double angle() { return atan2(y, x); }

  Point rotate(double theta) {
    static_assert(!is_integral<T>::value);
    double c = cos(theta), s = sin(theta);
    return Point{c * x - s * y, s * x + c * y};
  }
  Point rot90(bool ccw) { return (ccw ? Point{-y, x} : Point{y, -x}); }
};

#ifdef FASTIO
template <typename T>
void rd(Point<T>& p) {
  fastio::rd(p.x), fastio::rd(p.y);
}
template <typename T>
void wt(Point<T>& p) {
  fastio::wt(p.x);
  fastio::wt(' ');
  fastio::wt(p.y);
}
#endif

// A -> B -> C と進むときに、左に曲がるならば +1、右に曲がるならば -1
template <typename T>
int ccw(Point<T> A, Point<T> B, Point<T> C) {
  T x = (B - A).det(C - A);
  if (x > 0) return 1;
  if (x < 0) return -1;
  return 0;
}

template <typename REAL, typename T, typename U>
REAL dist(Point<T> A, Point<U> B) {
  REAL dx = REAL(A.x) - REAL(B.x);
  REAL dy = REAL(A.y) - REAL(B.y);
  return sqrt(dx * dx + dy * dy);
}

// ax+by+c
template <typename T>
struct Line {
  T a, b, c;

  Line(T a, T b, T c) : a(a), b(b), c(c) {}
  Line(Point<T> A, Point<T> B) {
    a = A.y - B.y, b = B.x - A.x, c = A.x * B.y - A.y * B.x;
  }
  Line(T x1, T y1, T x2, T y2) : Line(Point<T>(x1, y1), Point<T>(x2, y2)) {}

  template <typename U>
  U eval(Point<U> P) {
    return U(a) * P.x + U(b) * P.y + U(c);
  }

  template <typename U>
  T eval(U x, U y) {
    return a * x + b * y + c;
  }

  // 同じ直線が同じ a,b,c で表現されるようにする
  void normalize() {
    static_assert(is_same_v<T, int> || is_same_v<T, long long>);
    T g = gcd(gcd(abs(a), abs(b)), abs(c));
    a /= g, b /= g, c /= g;
    if (b < 0) {
      a = -a, b = -b, c = -c;
    }
    if (b == 0 && a < 0) {
      a = -a, b = -b, c = -c;
    }
  }

  bool is_parallel(Line other) { return a * other.b - b * other.a == 0; }
  bool is_orthogonal(Line other) { return a * other.a + b * other.b == 0; }
  bool is_same(Line other) {
    if (a * other.b != b * other.a) return 0;
    if (a * other.c != c * other.a) return 0;
    if (b * other.c != c * other.b) return 0;
    return 1;
  }
};

template <typename T>
struct Segment {
  Point<T> A, B;

  Segment(Point<T> A, Point<T> B) : A(A), B(B) {}
  Segment(T x1, T y1, T x2, T y2)
      : Segment(Point<T>(x1, y1), Point<T>(x2, y2)) {}

  bool contain(Point<T> C) {
    T det = (C - A).det(B - A);
    if (det != 0) return 0;
    return (C - A).dot(B - A) >= 0 && (C - B).dot(A - B) >= 0;
  }

  Line<T> to_line() { return Line(A, B); }
};

template <typename REAL>
struct Circle {
  Point<REAL> O;
  REAL r;
  Circle() {}
  Circle(Point<REAL> O, REAL r) : O(O), r(r) {}
  Circle(REAL x, REAL y, REAL r) : O(x, y), r(r) {}
  template <typename T>
  bool contain(Point<T> p) {
    REAL dx = p.x - O.x, dy = p.y - O.y;
    return dx * dx + dy * dy <= r * r;
  }
};
// END: geo/base.hpp
#line 5 "main.cpp"

/*
色 1 の円
色 2 の円
がある

色 1 の円の和集合面積は?
色 2 の円の和集合面積は?

色 1, 2 の円の和集合面積は?

これができればいいか

実は書いたことないんですが
そんなに難しくはないはずで
境界に現れる弧の寄与を足してくる

タイブレイク大丈夫か?
完全に一致する円に注意する!!

wow
長方形に制限みたいな要素も発生!?
まあ、やるか...


中心が外側!!
修正できるか?

*/

// using Re = long double;
// using Re = long double;
using Re = double;
using RE = long double;
const Re PI = acos(-1);

RE calc(ll XMAX, ll YMAX, vi X, vi Y, vi R) {
  using P = Point<ll>;

  ll N = len(X);
  SHOW(N);
  vc<Circle<ll>> C(N);
  FOR(i, N) C[i] = Circle<ll>(P(X[i], Y[i]), R[i]);

  vc<bool> out(N);
  FOR(i, N) {
    if (XMAX + R[i] <= C[i].O.x) out[i] = 1;
    if (YMAX + R[i] <= C[i].O.y) out[i] = 1;
    if (C[i].O.x <= -R[i]) out[i] = 1;
    if (C[i].O.y <= -R[i]) out[i] = 1;
  }

  RE ANS = 0;

  auto calc_c = [&](int i) -> void {
    if (out[i]) return;
    vc<pair<Re, int>> event;
    auto add = [&](Re s, Re t) -> void {
      FOR(k, -3, 4) {
        Re x = s + k * (2 * PI);
        Re y = t + k * (2 * PI);
        chmax(x, 0);
        chmin(y, PI + PI);
        if (x < y) {
          event.eb(x, 1), event.eb(y, -1);
        }
      }
    };
    FOR(j, N) {
      if (j == i) continue;
      // 一致
      if (C[i].O == C[j].O && C[i].r == C[j].r) {
        // 小さい方が境界に現れるとする
        if (j < i) return;
        continue;
      }

      Re d = (C[j].O - C[i].O).norm();
      if (d >= C[i].r + C[j].r) continue;
      if (d <= C[i].r - C[j].r) {
        // j is inside i
        continue;
      }
      if (d <= C[j].r - C[i].r) {
        // i is inside j
        return;
      }
      Re r1 = C[i].r, r2 = C[j].r;
      Re cos_v = (r1 * r1 + d * d - r2 * r2) / (2 * r1 * d);
      chmax(cos_v, -1), chmin(cos_v, 1);
      Re t = acos(cos_v);
      Re dir = (C[j].O - C[i].O).angle();
      add(dir - t, dir + t);
    }

    // bounding box
    {
      ll x = C[i].O.x;
      ll r = R[i];
      if (XMAX < x + r) {
        ll d = XMAX - x;
        Re t = acos(Re(d) / r);
        add(0 - t, 0 + t);
      }
    }
    {
      ll y = C[i].O.y;
      ll r = R[i];
      if (YMAX < y + r) {
        ll d = YMAX - y;
        Re t = acos(Re(d) / r);
        add(PI / 2 - t, PI / 2 + t);
      }
    }
    {
      ll x = C[i].O.x;
      ll r = R[i];
      if (x < r) {
        ll d = x;
        Re t = acos(Re(d) / r);
        add(PI - t, PI + t);
      }
    }
    {
      ll y = C[i].O.y;
      ll r = R[i];
      if (y < r) {
        ll d = y;
        Re t = acos(Re(d) / r);
        add(1.5 * PI - t, 1.5 * PI + t);
      }
    }

    sort(all(event));
    SHOW(event);
    auto add_range = [&](Re x, Re y) -> void {
      SHOW(x, y);
      Re ans = 0;
      ans += R[i] * R[i] * (y - x) / 2;
      using PR = Point<Re>;
      PR A(C[i].O);
      PR B, C;
      B.x = A.x + cos(x) * R[i];
      B.y = A.y + sin(x) * R[i];
      C.x = A.x + cos(y) * R[i];
      C.y = A.y + sin(y) * R[i];
      ans += A.det(C) * 0.5;
      ans -= A.det(B) * 0.5;
      SHOW(x, y, ans);
      ANS += ans;
    };
    Re x = 0;
    int now = 0;
    for (auto& [p, v] : event) {
      if (now == 0) add_range(x, p);
      now += v;
      x = p;
    }
    SHOW(x);
    add_range(x, PI + PI);
  };

  FOR(i, N) calc_c(i);

  SHOW(ANS);

  // あとは線分を引きます
  // おお実は右と上だけでよい
  // 右
  {
    vc<pair<Re, int>> event;
    auto add = [&](Re s, Re t) -> void {
      chmax(s, 0), chmin(t, YMAX);
      if (s < t) event.eb(s, 1), event.eb(t, -1);
    };

    FOR(i, N) {
      if (out[i]) continue;

      ll x = C[i].O.x;
      ll y = C[i].O.y;
      ll r = R[i];
      if (XMAX < x + r) {
        ll d = XMAX - x;
        Re h = sqrtl(r * r - d * d);
        add(y - h, y + h);
      }
    }

    auto add_range = [&](Re x, Re y) -> void { ANS += (y - x) * XMAX / 2; };

    sort(all(event));
    Re x = 0;
    int now = 0;
    for (auto& [p, v] : event) {
      if (now > 0) add_range(x, p);
      now += v;
      x = p;
    }
  }

  // 上
  {
    vc<pair<Re, int>> event;
    auto add = [&](Re s, Re t) -> void {
      chmax(s, 0), chmin(t, XMAX);
      if (s < t) event.eb(s, 1), event.eb(t, -1);
    };

    FOR(i, N) {
      if (out[i]) continue;
      ll x = C[i].O.x;
      ll y = C[i].O.y;
      ll r = R[i];
      if (YMAX < y + r) {
        ll d = YMAX - y;
        Re h = sqrtl(r * r - d * d);
        add(x - h, x + h);
      }
    }

    auto add_range = [&](Re x, Re y) -> void { ANS += (y - x) * YMAX / 2; };

    sort(all(event));
    Re x = 0;
    int now = 0;
    for (auto& [p, v] : event) {
      if (now > 0) add_range(x, p);
      now += v;
      x = p;
    }
  }
  SHOW(ANS);
  return ANS;
}

void solve() {
  LL(XMAX, YMAX, N);
  vi X(N), Y(N), R(N), D(N);
  FOR(i, N) {
    read(X[i], Y[i], R[i]);
    CHAR(ch);
    D[i] = (ch == 'V' ? 1 : 2);
  }

  auto work = [&](int s) -> Re {
    vi XX, YY, RR;
    FOR(i, N) {
      if (!(s & D[i])) continue;
      XX.eb(X[i]);
      YY.eb(Y[i]);
      RR.eb(R[i]);
    }
    SHOW(XX, YY, RR);
    return calc(XMAX, YMAX, XX, YY, RR);
  };

  vc<RE> A(4);
  FOR(s, 4) A[s] = work(s);

  A[1] -= A[3];
  A[2] -= A[3];
  A[0] = XMAX * YMAX - A[1] - A[2] - A[3];

  RE ans = 0;
  ans += 1.0 * A[0];
  ans += 0.5 * (A[1] + A[2]);
  // print(A);
  print(ans);
}

signed main() { solve(); }
// END: main.cpp
0