#line 1 "test/yc_1036_bisect.test.cpp" #define PROBLEM "https://yukicoder.me/problems/no/1036" #include #include #include #include #line 1 "DataStructure/basic_segment_tree.cpp" /** * @brief 単一更新セグメント木 * @author えびちゃん */ #include #line 12 "DataStructure/basic_segment_tree.cpp" template class basic_segment_tree { public: using value_type = Monoid; using size_type = size_t; private: std::vector M_c; size_type M_n; std::vector M_covering_segments(size_type l, size_type r) const { std::vector 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 basic_segment_tree(InputIt first, InputIt last) { std::vector 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 void assign(InputIt first, InputIt last) { std::vector 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 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 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 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 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 9 "test/yc_1036_bisect.test.cpp" template class gcd_monoid { public: using value_type = Tp; private: value_type M_x = 0; static value_type S_gcd(value_type x, value_type y) { while (y) std::swap(x %= y, y); return x; } public: gcd_monoid() = default; // identity gcd_monoid(value_type const& x): M_x(x) {} gcd_monoid& operator +=(gcd_monoid const& that) { M_x = S_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 a(n); for (auto& ai: a) scanf("%jd", &ai); basic_segment_tree> 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); }