結果
問題 |
No.1036 Make One With GCD 2
|
ユーザー |
![]() |
提出日時 | 2020-04-25 19:58:33 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 735 ms / 2,000 ms |
コード長 | 4,964 bytes |
コンパイル時間 | 880 ms |
コンパイル使用メモリ | 67,048 KB |
最終ジャッジ日時 | 2025-01-10 01:27:52 |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 4 |
other | AC * 41 |
コンパイルメッセージ
test/yc_1036_bisect.test.cpp: In function ‘int main()’: test/yc_1036_bisect.test.cpp:42:8: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] test/yc_1036_bisect.test.cpp:45:26: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
ソースコード
#line 1 "test/yc_1036_bisect.test.cpp" #define PROBLEM "https://yukicoder.me/problems/no/1036" #include <cstdint> #include <cstdio> #include <algorithm> #include <numeric> #include <vector> #line 1 "DataStructure/basic_segment_tree.cpp" /** * @brief 単一更新セグメント木 * @author えびちゃん */ #include <cstddef> #line 12 "DataStructure/basic_segment_tree.cpp" template <typename Monoid> class basic_segment_tree { public: using value_type = Monoid; using size_type = size_t; private: std::vector<value_type> M_c; size_type M_n; std::vector<size_type> M_covering_segments(size_type l, size_type r) const { std::vector<size_type> left, right; l += M_n; r += M_n; while (l < r) { if (l & 1) left.push_back(l++); if (r & 1) right.push_back(--r); l >>= 1; r >>= 1; } left.insert(left.end(), right.rbegin(), right.rend()); return left; } public: basic_segment_tree() = default; explicit basic_segment_tree(size_type n): M_c(n+n), M_n(n) {} explicit basic_segment_tree(size_type n, value_type const& x): M_c(n+n, x), M_n(n) { for (size_type i = n; i--;) M_c[i] = M_c[i<<1|0] + M_c[i<<1|1]; } template <typename InputIt> basic_segment_tree(InputIt first, InputIt last) { std::vector<value_type> tmp(first, last); M_n = tmp.size(); M_c.resize(M_n); M_c.insert(M_c.end(), tmp.begin(), tmp.end()); for (size_type i = M_n; i--;) M_c[i] = M_c[i<<1|0] + M_c[i<<1|1]; } void assign(size_type n, value_type const& x) { M_c.assign(n+n, x); M_n = n; for (size_type i = n; i--;) M_c[i] = M_c[i<<1|0] + M_c[i<<1|1]; } template <typename InputIt> void assign(InputIt first, InputIt last) { std::vector<value_type> tmp(first, last); M_n = tmp.size(); M_c.resize(M_n); M_c.insert(M_c.end(), tmp.begin(), tmp.end()); for (size_type i = M_n; i--;) M_c[i] = M_c[i<<1|0] + M_c[i<<1|1]; } void set(size_type i, value_type const& x) { i += M_n; M_c[i] = x; while (i > 1) { i >>= 1; M_c[i] = M_c[i<<1|0] + M_c[i<<1|1]; } } void set(size_type i, value_type&& x) { i += M_n; M_c[i] = std::move(x); while (i > 1) { i >>= 1; M_c[i] = M_c[i<<1|0] + M_c[i<<1|1]; } } value_type const& operator [](size_type i) const { return M_c[i + M_n]; } value_type fold(size_type l, size_type r) const { value_type resl{}, resr{}; l += M_n; r += M_n; while (l < r) { if (l & 1) resl += M_c[l++]; if (r & 1) resr = M_c[--r] + std::move(resr); l >>= 1; r >>= 1; } return resl += resr; } template <typename Predicate> size_type foldl_bisect(size_type l, Predicate pred) const { if (l == M_n) return l; value_type x{}; size_type v = M_n+M_n; std::vector<size_type> cs = M_covering_segments(l, M_n); // search the subroot for (auto s: cs) { if (!pred(x + M_c[s])) { v = s; break; } x += M_c[s]; } // search the leaf while (v < M_n) { v <<= 1; if (pred(x + M_c[v])) { x += M_c[v]; v |= 1; } } return v - M_n; } template <typename Predicate> size_type foldr_bisect(size_type r, Predicate pred) const { if (r == 0) return r; value_type x{}; size_type v = M_n+M_n; std::vector<size_type> cs = M_covering_segments(0, r); std::reverse(cs.begin(), cs.end()); // search the subroot for (auto s: cs) { if (!pred(M_c[s] + x)) { v = s; break; } x = M_c[s] + std::move(x); } if (v == M_n+M_n) return -1; // always true // search the leaf while (v < M_n) { v <<= 1; if (pred(M_c[v|1] + x)) { x = M_c[v|1] + std::move(x); } else { v |= 1; } } return v - M_n; } }; #line 10 "test/yc_1036_bisect.test.cpp" template <typename Tp> class gcd_monoid { public: using value_type = Tp; private: value_type M_x = 0; public: gcd_monoid() = default; // identity gcd_monoid(value_type const& x): M_x(x) {} gcd_monoid& operator +=(gcd_monoid const& that) { M_x = std::gcd(M_x, that.M_x); return *this; } friend bool operator ==(gcd_monoid const& lhs, gcd_monoid const& rhs) { return lhs.M_x == rhs.M_x; } friend gcd_monoid operator +(gcd_monoid lhs, gcd_monoid const& rhs) { return lhs += rhs; } friend bool operator !=(gcd_monoid const& lhs, gcd_monoid const& rhs) { return !(lhs == rhs); } value_type const& get() const { return M_x; } }; int main() { size_t n; scanf("%zu", &n); std::vector<intmax_t> a(n); for (auto& ai: a) scanf("%jd", &ai); basic_segment_tree<gcd_monoid<intmax_t>> st(a.begin(), a.end()); auto pred = [](auto x) { return x.get() > 1; }; intmax_t res = 0; for (size_t i = 0; i < n; ++i) { size_t j = st.foldl_bisect(i, pred); if (j <= n) res += n-j; } printf("%jd\n", res); }