結果
| 問題 | No.3017 交互浴 |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-12-31 00:11:14 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.89.0) |
| 結果 |
AC
|
| 実行時間 | 143 ms / 2,000 ms |
| コード長 | 12,515 bytes |
| 記録 | |
| コンパイル時間 | 4,135 ms |
| コンパイル使用メモリ | 285,988 KB |
| 実行使用メモリ | 7,940 KB |
| 最終ジャッジ日時 | 2025-12-31 00:11:32 |
| 合計ジャッジ時間 | 17,759 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 55 |
ソースコード
#include <limits>
#ifndef __DEBUG_HPP__
#define __DEBUG_HPP__
#ifndef __TOOLS_HPP__
#define __TOOLS_HPP__
#include <bits/stdc++.h>
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<int>;
using VVi = vector<Vi>;
using Pi = pair<int, int>;
using VPi = vector<Pi>;
using V = vector<long long>;
using VV = vector<V>;
using P = pair<long long, long long>;
using VP = vector<P>;
using Vb = vector<bool>;
// 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 <class T, class U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {
os << "(" << p.first << " " << p.second << ")";
return os;
}
template <class T, class U>
istream& operator>>(istream& is, pair<T, U>& p) {
is >> p.first >> p.second;
return is;
}
// vector
template <class T>
ostream& operator<<(ostream& os, const vector<T>& v) {
rep(i, v.size()) {
if (i) os << " ";
os << v[i];
}
return os;
}
template <class T>
istream& operator>>(istream& is, vector<T>& v) {
rep(i, v.size()) { is >> v[i]; }
return is;
}
// multi-variable
void input() {}
template <typename T, class... U>
void input(T& t, U&... u) {
cin >> t;
input(u...);
}
void output() { cout << '\n'; }
template <typename T, class... U, char seperate = ' '>
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 <typename T>
static constexpr T safe_max() noexcept {
return numeric_limits<T>::max() / (T)2 - (T)1;
};
constexpr long long INFLL = safe_max<long long>();
constexpr int INF = safe_max<int>();
const double PI = acos(-1);
#endif // __CONSTANCE_HPP__
#ifndef __TRANSIENT_HPP__
#define __TRANSIENT_HPP__
template <class T>
inline bool chmax(T& a, T b) {
if (a < b) {
a = b;
return 1;
}
return 0;
}
template <class T>
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 <typename U, typename = void>
struct is_specialize : false_type {};
template <typename U>
struct is_specialize<
U, typename conditional<false, typename U::iterator, void>::type>
: true_type {};
template <typename U>
struct is_specialize<
U, typename conditional<false, decltype(U::first), void>::type>
: true_type {};
template <typename U>
struct is_specialize<U, enable_if_t<is_integral<U>::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 <typename U,
enable_if_t<!is_specialize<U>::value, nullptr_t> = nullptr>
void dump(const U& t) {
cerr << t;
}
template <typename T>
void dump(const T& t, enable_if_t<is_integral<T>::value>* = nullptr) {
string res;
if (t == INF) res = "inf";
if constexpr (is_signed<T>::value) {
if (t == -INF) res = "-inf";
}
if constexpr (sizeof(T) == 8) {
if (t == INFLL) res = "inf";
if constexpr (is_signed<T>::value) {
if (t == INFLL) res = "-inf";
}
}
if (res.empty()) res = to_string(t);
cerr << res;
}
template <typename T, typename U>
void dump(const pair<T, U>&);
template <typename T>
void dump(const pair<T*, int>&);
template <typename T>
void dump(const T& t,
enable_if_t<!is_void<typename T::iterator>::value>* = nullptr) {
cerr << "[ ";
for (auto it = t.begin(); it != t.end();) {
dump(*it);
cerr << (++it == t.end() ? "" : ", ");
}
cerr << " ]";
}
template <typename T, typename U>
void dump(const pair<T, U>& t) {
cerr << "( ";
dump(t.first);
cerr << ", ";
dump(t.second);
cerr << " )";
}
template <typename T>
void dump(const pair<T*, int>& 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 <typename Head, typename... Tail>
void trace(Head&& head, Tail&&... tail) {
cerr << " ";
dump(head);
if (sizeof...(tail) != 0) cerr << ",";
trace(forward<Tail>(tail)...);
}
#else
void dump(const int& t) { }
void dump(const char& t) {}
void dump(const string& t) {}
void dump(const bool& t) {}
template <typename U,
enable_if_t<!is_specialize<U>::value, nullptr_t> = nullptr>
void dump(const U& t) {}
template <typename T>
void dump(const T& t, enable_if_t<is_integral<T>::value>* = nullptr) {}
template <typename T, typename U>
void dump(const pair<T, U>&);
template <typename T>
void dump(const pair<T*, int>&);
template <typename T>
void dump(const T& t,
enable_if_t<!is_void<typename T::iterator>::value>* = nullptr) {}
template <typename T, typename U>
void dump(const pair<T, U>& t) {}
template <typename T>
void dump(const pair<T*, int>& t) {}
void trace() {}
template <typename Head, typename... Tail>
void trace(Head&& head, Tail&&... tail) {}
#endif //__LOCAL__
#endif // __DEBUG_HPP__
using namespace std;
template <class T, class VAL = long long>
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<Node> nodes;
IntervalSet() : nodes() {}
constexpr typename set<Node>::iterator begin() { return nodes.begin(); }
constexpr typename set<Node>::iterator end() { return nodes.end(); }
constexpr typename set<Node>::iterator get_range(const T& x) {
// xが含まれる区間を返す。含まれない場合はendを返す
auto itr = nodes.upper_bound(Node(x, numeric_limits<T>::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<T>::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<ll> hights;
static Input read() {
ini(n);
vector<ll> hights(n);
inv1(hights);
return Input{hights};
}
};
void solve(const Input& input, IntervalSet<ll, int>& 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<long long, int> is;
solve(input, is);
return 0;
}