#include #ifndef __DEBUG_HPP__ #define __DEBUG_HPP__ #ifndef __TOOLS_HPP__ #define __TOOLS_HPP__ #include using namespace std; // #ifndef __IO_HPP__ #define __IO_HPP__ // 入出力関連 #ifndef __MACRO_HPP__ #define __MACRO_HPP__ using ll = long long; #define rep(i, n) for (int i = 0, i##_len = (int)(n); i < i##_len; ++i) #define reps(i, n) for (int i = 1, i##_len = (int)(n); i <= i##_len; ++i) #define rrep(i, n) for (int i = ((int)(n)-1); i >= 0; --i) #define rreps(i, n) for (int i = ((int)(n)); i > 0; --i) #define repi(i, x) \ for (auto i = (x).begin(), i##_fin = (x).end(); i != i##_fin; ++i) #define all(x) (x).begin(), (x).end() #define F first #define S second #define mp make_pair #define mt make_tuple #define pb push_back #define eb emplace_back using Vi = vector; using VVi = vector; using Pi = pair; using VPi = vector; using V = vector; using VV = vector; using P = pair; using VP = vector

; using Vb = vector; // decler and input #define ini(...) \ int __VA_ARGS__; \ input(__VA_ARGS__); #define inl(...) \ long long __VA_ARGS__; \ input(__VA_ARGS__); #define ind(...) \ double __VA_ARGS__; \ input(__VA_ARGS__); #define ins(...) \ string __VA_ARGS__; \ input(__VA_ARGS__); #define inv1(s) rep(i, (s).size()) input(s[i]); #define inv2(s, t) rep(i, (s).size()) input(s[i], t[i]); #define inv3(s, t, u) rep(i, (s).size()) input(s[i], t[i], u[i]); #define inv4(s, t, u, v) rep(i, (s).size()) input(s[i], t[i], u[i], v[i]); #endif //__MACRO_HPP__ // pair template ostream& operator<<(ostream& os, const pair& p) { os << "(" << p.first << " " << p.second << ")"; return os; } template istream& operator>>(istream& is, pair& p) { is >> p.first >> p.second; return is; } // vector template ostream& operator<<(ostream& os, const vector& v) { rep(i, v.size()) { if (i) os << " "; os << v[i]; } return os; } template istream& operator>>(istream& is, vector& v) { rep(i, v.size()) { is >> v[i]; } return is; } // multi-variable void input() {} template void input(T& t, U&... u) { cin >> t; input(u...); } void output() { cout << '\n'; } template void output(const T& t, const U&... u) { cout << t; if (sizeof...(u)) cout << seperate; output(u...); } // setup struct IoSetuper { IoSetuper() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(15); cerr << fixed << setprecision(7); } } iosetuper; #endif //__IO_HPP__ #ifndef __CONSTANCE_HPP__ #define __CONSTANCE_HPP__ template static constexpr T safe_max() noexcept { return numeric_limits::max() / (T)2 - (T)1; }; constexpr long long INFLL = safe_max(); constexpr int INF = safe_max(); const double PI = acos(-1); #endif // __CONSTANCE_HPP__ #ifndef __TRANSIENT_HPP__ #define __TRANSIENT_HPP__ template inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; } template inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; } #endif // __TRANSIENT_HPP__ /* #ifdef LOCAL #define dbg(x) cerr << #x << ": " << (x) << '\n' #define say(x) cerr << (x) << '\n' #else #define dbg(x) #define say(x) #endif */ string solve(bool a) { return ((a) ? "Yes" : "No"); } #endif // __TOOLS_HPP__ // template struct is_specialize : false_type {}; template struct is_specialize< U, typename conditional::type> : true_type {}; template struct is_specialize< U, typename conditional::type> : true_type {}; template struct is_specialize::value, void>> : true_type { }; #ifdef LOCAL void dump(const int& t) { cerr << t; } void dump(const char& t) { cerr << t; } void dump(const string& t) { cerr << t; } void dump(const bool& t) { cerr << (t ? "true" : "false"); } template ::value, nullptr_t> = nullptr> void dump(const U& t) { cerr << t; } template void dump(const T& t, enable_if_t::value>* = nullptr) { string res; if (t == INF) res = "inf"; if constexpr (is_signed::value) { if (t == -INF) res = "-inf"; } if constexpr (sizeof(T) == 8) { if (t == INFLL) res = "inf"; if constexpr (is_signed::value) { if (t == INFLL) res = "-inf"; } } if (res.empty()) res = to_string(t); cerr << res; } template void dump(const pair&); template void dump(const pair&); template void dump(const T& t, enable_if_t::value>* = nullptr) { cerr << "[ "; for (auto it = t.begin(); it != t.end();) { dump(*it); cerr << (++it == t.end() ? "" : ", "); } cerr << " ]"; } template void dump(const pair& t) { cerr << "( "; dump(t.first); cerr << ", "; dump(t.second); cerr << " )"; } template void dump(const pair& t) { cerr << "[ "; for (int i = 0; i < t.second; i++) { dump(t.first[i]); cerr << (i == t.second - 1 ? "" : ", "); } cerr << " ]"; } void trace() { cerr << endl; } template void trace(Head&& head, Tail&&... tail) { cerr << " "; dump(head); if (sizeof...(tail) != 0) cerr << ","; trace(forward(tail)...); } #else void dump(const int& t) { } void dump(const char& t) {} void dump(const string& t) {} void dump(const bool& t) {} template ::value, nullptr_t> = nullptr> void dump(const U& t) {} template void dump(const T& t, enable_if_t::value>* = nullptr) {} template void dump(const pair&); template void dump(const pair&); template void dump(const T& t, enable_if_t::value>* = nullptr) {} template void dump(const pair& t) {} template void dump(const pair& t) {} void trace() {} template void trace(Head&& head, Tail&&... tail) {} #endif //__LOCAL__ #endif // __DEBUG_HPP__ using namespace std; template struct IntervalSet { struct Node { T left; T right; VAL value; Node(const T& l, const T& r, const VAL& v) : left(l), right(r), value(v) {} bool operator<(const Node& rhs) const { if (left != rhs.left) return left < rhs.left; // 左端で比較 return right < rhs.right; // 左端が同じならば右端で比較 }; friend ostream& operator<<(ostream& os, const Node& node) { os << "[" << node.left << ", " << node.right << "): " << node.value; return os; } }; set nodes; IntervalSet() : nodes() {} constexpr typename set::iterator begin() { return nodes.begin(); } constexpr typename set::iterator end() { return nodes.end(); } constexpr typename set::iterator get_range(const T& x) { // xが含まれる区間を返す。含まれない場合はendを返す auto itr = nodes.upper_bound(Node(x, numeric_limits::max(), 0)); if (itr != nodes.begin()) { itr = prev(itr); trace("get_range:", *itr); if (itr->left <= x && x < itr->right) { // xが区間に含まれる trace("found range"); return itr; } } return nodes.end(); } constexpr T get_mex(const T& x) { // x以上かつ現在の区間に登録されていない最小値を返す auto itr = nodes.upper_bound(Node(x, numeric_limits::max(), 0)); if (itr != nodes.begin()) { itr = prev(itr); if (itr->left <= x && x < itr->right) { // xが区間に含まれる return itr->right; } } return x; } VAL insert(T left, T right, VAL value) { // 区間 [left, right)に値valueを挿入 VAL res = 0; T to_add_left = left; ; T to_add_right = right; trace("insert [", left, right, ")"); auto itr = nodes.lower_bound(Node(left, 0, 0)); if (itr != nodes.end()) { trace("insert before:", *itr); } else { trace("insert before: end"); } // 領域右側でかぶるかの確認を行う while (itr != nodes.end() and itr->left <= right) { // 領域が完全にかぶる場合 if (left <= itr->left and itr->right <= right) { trace("case 1(full overlap)", *itr); res -= (itr->right - itr->left) * itr->value; itr = nodes.erase(itr); } else if (left <= itr->left and itr->left <= right and right < itr->right) { // 領域の左側が一部でもかぶる場合 trace("case 2(left partial overlap)", *itr); T r = itr->right; VAL v = itr->value; res -= (itr->right - itr->left) * itr->value; itr = nodes.erase(itr); to_add_right = r; break; } else { break; } } trace("back to begin"); // 領域の左側でかぶるかの確認を行う if (itr != nodes.begin()) { itr = prev(itr); // 領域に重ならない if (itr->right < left) { trace("no overlap", *itr); } else if (itr->left <= left && left <= itr->right && itr->right <= right) { // 領域の右側にかぶる trace("case 3(right partial overlap)", *itr); T l = itr->left; VAL v = itr->value; res -= (itr->right - itr->left) * itr->value; itr = nodes.erase(itr); to_add_left = l; } else if ( itr->left<= left &&right <= itr->right ) { // 領域が完全にかぶる trace("case 4(full overlap)", *itr); return 0; } } nodes.insert(Node(to_add_left, to_add_right, value)); return res + (to_add_right - to_add_left) * value; } VAL remove(T left, T right) { VAL res = 0; // 区間 [left, right)を削除 // [ ]( ) [ ] // [ ] ([ ]) [ ] // [ (] [ ) ]; trace("current intrvals:"); this->dump(); trace("end of intervals"); auto itr = nodes.lower_bound(Node(left, 0, 0)); while (itr != nodes.end() && itr->left <= right) { // 2番目以降の区間を担当する if (left <= itr->left && itr->right <= right) { // 完全に囲んでいる: [ ) [[ [ ) )) [ ) trace("case 1(range all erase)", *itr); res -= (itr->right - itr->left) * itr->value; itr = nodes.erase(itr); continue; } else if (itr->left < right && right <= itr->right) { // 左側が削除領域にかぶっている trace("case 2(range left erase)", *itr); T r = itr->right; VAL v = itr->value; res -= (itr->right - itr->left) * itr->value; itr = nodes.erase(itr); res += insert(right, r, v); itr = nodes.lower_bound(Node(left, 0, 0)); break; } else { break; } } trace("back to begin"); // 先頭の区間を担当する if (itr != nodes.begin()) { itr = prev(itr); // 領域に重ならない if (itr->right <= left) { trace("no overlap", *itr); } else if (itr->left <= left && right <= itr->right) { // 領域の一部が削除領域にかぶっている trace("case 3 (range partial erase)", *itr); T l = itr->left; T r = itr->right; VAL v = itr->value; res -= (itr->right - itr->left) * itr->value; itr = nodes.erase(itr); res += insert(l, left, v); res += insert(right, r, v); } else if (itr->left <= left && itr->right < right) { // 右側が削除領域にかぶっている trace("case 4(range right erase)", *itr); T l = itr->left; VAL v = itr->value; res -= (itr->right - itr->left) * itr->value; itr = nodes.erase(itr); res += insert(l, left, v); } } return res; } void dump() { trace(this->nodes); } }; // https://yukicoder.me/problems/no/3017 struct Input { vector hights; static Input read() { ini(n); vector hights(n); inv1(hights); return Input{hights}; } }; void solve(const Input& input, IntervalSet& is) { long long cray_length = 0LL; for(int i = 0; i < input.hights.size(); i++) { if (i % 2 == 0) { cray_length+=is.insert(0, input.hights[i] , 1); } else { cray_length+=is.remove(0, input.hights[i] ); } output(cray_length); } } int main() { auto input = Input::read(); IntervalSet is; solve(input, is); return 0; }