結果
問題 | No.1234 典型RMQ |
ユーザー | mai |
提出日時 | 2020-09-18 21:52:20 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 106 ms / 2,000 ms |
コード長 | 13,870 bytes |
コンパイル時間 | 3,317 ms |
コンパイル使用メモリ | 229,176 KB |
実行使用メモリ | 9,472 KB |
最終ジャッジ日時 | 2024-11-09 01:48:43 |
合計ジャッジ時間 | 6,778 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,248 KB |
testcase_02 | AC | 2 ms
5,248 KB |
testcase_03 | AC | 2 ms
5,248 KB |
testcase_04 | AC | 2 ms
5,248 KB |
testcase_05 | AC | 2 ms
5,248 KB |
testcase_06 | AC | 93 ms
9,344 KB |
testcase_07 | AC | 69 ms
5,248 KB |
testcase_08 | AC | 102 ms
9,300 KB |
testcase_09 | AC | 84 ms
6,272 KB |
testcase_10 | AC | 101 ms
9,344 KB |
testcase_11 | AC | 92 ms
9,332 KB |
testcase_12 | AC | 81 ms
6,272 KB |
testcase_13 | AC | 68 ms
5,248 KB |
testcase_14 | AC | 85 ms
6,272 KB |
testcase_15 | AC | 83 ms
6,400 KB |
testcase_16 | AC | 104 ms
9,344 KB |
testcase_17 | AC | 86 ms
6,400 KB |
testcase_18 | AC | 60 ms
5,248 KB |
testcase_19 | AC | 106 ms
9,336 KB |
testcase_20 | AC | 47 ms
9,472 KB |
testcase_21 | AC | 97 ms
9,404 KB |
testcase_22 | AC | 57 ms
9,344 KB |
testcase_23 | AC | 60 ms
9,412 KB |
testcase_24 | AC | 60 ms
9,340 KB |
testcase_25 | AC | 60 ms
9,348 KB |
testcase_26 | AC | 60 ms
9,244 KB |
testcase_27 | AC | 2 ms
5,248 KB |
testcase_28 | AC | 2 ms
5,248 KB |
testcase_29 | AC | 1 ms
5,248 KB |
ソースコード
#pragma GCC optimize ("O3") #include "bits/stdc++.h" using namespace std; using ll = long long int; #define all(v) (v).begin(),(v).end() #define repeat(cnt,l) for(typename remove_const<typename remove_reference<decltype(l)>::type>::type cnt={};(cnt)<(l);++(cnt)) #define rrepeat(cnt,l) for(auto cnt=(l)-1;0<=(cnt);--(cnt)) #define iterate(cnt,b,e) for(auto cnt=(b);(cnt)!=(e);++(cnt)) #define diterate(cnt,b,e) for(auto cnt=(b);(cnt)!=(e);--(cnt)) const long long MD = 1000000007ll; const long double PI = 3.1415926535897932384626433832795L; template<typename T1, typename T2> inline ostream& operator <<(ostream &o, const pair<T1, T2> p) { o << '(' << p.first << ':' << p.second << ')'; return o; } template<typename T> inline T& chmax(T& to, const T& val) { return to = max(to, val); } template<typename T> inline T& chmin(T& to, const T& val) { return to = min(to, val); } void bye(string s, int code = 0) { cout << s << endl; exit(code); } mt19937_64 randdev(8901016); template<typename T, typename Random = decltype(randdev), typename enable_if<is_integral<T>::value>::type* = nullptr> inline T rand(T l, T h, Random& rand = randdev) { return uniform_int_distribution<T>(l, h)(rand); } template<typename T, typename Random = decltype(randdev), typename enable_if<is_floating_point<T>::value>::type* = nullptr> inline T rand(T l, T h, Random& rand = randdev) { return uniform_real_distribution<T>(l, h)(rand); } template <typename I> struct MyRangeFormat{ I b,e; MyRangeFormat(I _b, I _e):b(_b),e(_e){} }; template<typename I> static ostream& operator<<(ostream& o, const MyRangeFormat<I>& f) { o << "[ "; iterate(i,f.b,f.e) o<<*i<<' '; return o << ']'; } template <typename I> struct MyMatrixFormat{ const I& p; long long n, m; MyMatrixFormat(const I& _p, long long _n, long long _m):p(_p),n(_n),m(_m){} }; template<typename I> static ostream& operator<<(ostream& o, const MyMatrixFormat<I>& f) { o<<'\n'; repeat(i,(f.n)) { repeat(j,f.m) o<<f.p[i][j]<<' '; o<<'\n'; } return o; } struct LOG_t { ~LOG_t() { cout << endl; } }; #define LOG (LOG_t(),cout<<'L'<<__LINE__<<": ") #define FMTA(m,w) (MyRangeFormat<decltype(m+0)>(m,m+w)) #define FMTR(b,e) (MyRangeFormat<decltype(e)>(b,e)) #define FMTV(v) FMTR(v.begin(),v.end()) #define FMTM(m,h,w) (MyMatrixFormat<decltype(m+0)>(m,h,w)) #if defined(_WIN32) || defined(_WIN64) #define getc_x _getc_nolock #define putc_x _putc_nolock #elif defined(__GNUC__) #define getc_x getc_unlocked #define putc_x putc_unlocked #else #define getc_x getc #define putc_x putc #endif class MaiScanner { FILE* fp_; constexpr bool isvisiblechar(char c) noexcept { return (0x21<=(c)&&(c)<=0x7E); } public: inline MaiScanner(FILE* fp):fp_(fp){} template<typename T> void input_integer(T& var) noexcept { var = 0; T sign = 1; int cc = getc_x(fp_); for (; cc < '0' || '9' < cc; cc = getc_x(fp_)) if (cc == '-') sign = -1; for (; '0' <= cc && cc <= '9'; cc = getc_x(fp_)) var = (var << 3) + (var << 1) + cc - '0'; var = var * sign; } inline int c() noexcept { return getc_x(fp_); } template<typename T, typename enable_if<is_integral<T>::value, nullptr_t>::type = nullptr> inline MaiScanner& operator>>(T& var) noexcept { input_integer<T>(var); return *this; } inline MaiScanner& operator>>(string& var) { int cc = getc_x(fp_); for (; !isvisiblechar(cc); cc = getc_x(fp_)); for (; isvisiblechar(cc); cc = getc_x(fp_)) var.push_back(cc); return *this; } template<typename IT> inline void in(IT begin, IT end) { for (auto it = begin; it != end; ++it) *this >> *it; } }; class MaiPrinter { FILE* fp_; public: inline MaiPrinter(FILE* fp):fp_(fp){} template<typename T> void output_integer(T var) noexcept { if (var == 0) { putc_x('0', fp_); return; } if (var < 0) putc_x('-', fp_), var = -var; char stack[32]; int stack_p = 0; while (var) stack[stack_p++] = '0' + (var % 10), var /= 10; while (stack_p) putc_x(stack[--stack_p], fp_); } inline MaiPrinter& operator<<(char c) noexcept { putc_x(c, fp_); return *this; } template<typename T, typename enable_if<is_integral<T>::value, nullptr_t>::type = nullptr> inline MaiPrinter& operator<<(T var) noexcept { output_integer<T>(var); return *this; } inline MaiPrinter& operator<<(char* str_p) noexcept { while (*str_p) putc_x(*(str_p++), fp_); return *this; } inline MaiPrinter& operator<<(const string& str) { const char* p = str.c_str(); const char* l = p + str.size(); while (p < l) putc_x(*p++, fp_); return *this; } template<typename IT> void join(IT begin, IT end, char sep = ' ') { for (bool b = 0; begin != end; ++begin, b = 1) b ? *this << sep << *begin : *this << *begin; } }; MaiScanner scanner(stdin); MaiPrinter printer(stdout); template <typename T> // using T = ll; class SegmentTree { public: struct IdxVal { int index; T value; inline IdxVal(int _i = 0, const T& _v = T()) : index(_i), value(_v) {} inline void set(int i, const T& v) { index = i; value = v; } inline bool operator<(const T& t) const { return value < t; } inline bool operator==(const T& t) const { return value == t; } inline bool operator<(const IdxVal& iv) const { return value < iv.value || (value == iv.value && index < iv.index); } inline bool operator==(const IdxVal& iv) const { return index == iv.index && value == iv.value; } }; enum struct Cmd { None, Add, Flat }; struct Node { T sum, lazyValue; IdxVal max; Cmd lazyType; }; private: const int size_; vector<T> leaf_data_; vector<Node> node_data_; T* leaf_; Node* node_; void _resize() { leaf_data_.resize(size_); node_data_.resize(size_ - 1); leaf_ = &leaf_data_[0]; node_ = &node_data_[0] - 1; } void _init() { for (int i = size_ - 1; 0 < i; --i) { int c = i << 1; if (size_ <= c) node_[i].max.set(c - size_, leaf_[c - size_]); else node_[i].max = node_[c].max; node_[i].lazyType = Cmd::None; node_[i].sum = node_[i].lazyValue = 0; } } public: inline void fill(T val) { std::fill(leaf_data_.begin(), leaf_data_.end(), val); _init(); } SegmentTree(int _n) : size_([](int _n) { int s = 8; while (s < _n) s <<= 1; return s; }(_n)) { _resize(); _init(); } SegmentTree(int _n, const T& _fillVal) : size_([](int _n) { int s = 8; while (s < _n) s <<= 1; return s; }(_n)) { _resize(); fill(_fillVal); } private: // lazyを適応する(子を呼ぶ前に呼ぶ) // width: ptrが担当するnodeの範囲の大きさ(ptr = 1 ならば size_) inline void _applyDown(int ptr, int width) { width >>= 1; // if (size_ <= ptr) return; if (node_[ptr].lazyType == Cmd::Add) { int c = ptr << 1; if (size_ <= c) { leaf_[c - size_] += node_[ptr].lazyValue; leaf_[c + 1 - size_] += node_[ptr].lazyValue; } else { node_[c].sum += node_[ptr].lazyValue * width; node_[c].max.value += node_[ptr].lazyValue; node_[c].lazyValue += node_[ptr].lazyValue; if (node_[c].lazyType == Cmd::None) node_[c].lazyType = Cmd::Add; node_[c + 1].sum += node_[ptr].lazyValue * width; node_[c + 1].max.value += node_[ptr].lazyValue; node_[c + 1].lazyValue += node_[ptr].lazyValue; if (node_[c + 1].lazyType == Cmd::None) node_[c + 1].lazyType = Cmd::Add; } node_[ptr].lazyType = Cmd::None; node_[ptr].lazyValue = 0; } else if (node_[ptr].lazyType == Cmd::Flat) { node_[ptr].lazyType = Cmd::None; int c = ptr << 1; if (size_ <= c) { leaf_[c - size_] = node_[ptr].lazyValue; leaf_[c + 1 - size_] = node_[ptr].lazyValue; } else { node_[c].sum = node_[ptr].lazyValue * width; node_[c].max.value = node_[ptr].lazyValue; node_[c].lazyValue = node_[ptr].lazyValue; node_[c].lazyType = Cmd::Flat; node_[c + 1].sum = node_[ptr].lazyValue * width; node_[c + 1].max.value = node_[ptr].lazyValue; node_[c + 1].lazyValue = node_[ptr].lazyValue; node_[c + 1].lazyType = Cmd::Flat; } node_[ptr].lazyType = Cmd::None; node_[ptr].lazyValue = 0; } } // lazyを適応する(子を呼んだ後に呼ぶ) inline void _applyUp(int ptr) { if (size_ <= ptr << 1) { int i = (ptr << 1) - size_; if (leaf_[i] < leaf_[i + 1]) node_[ptr].max.set(i + 1, leaf_[i + 1]); else node_[ptr].max.set(i, leaf_[i]); node_[ptr].sum = leaf_[i] + leaf_[i + 1]; } else { if (node_[(ptr << 1)].max.value < node_[(ptr << 1) + 1].max.value) node_[ptr].max = node_[(ptr << 1) + 1].max; else node_[ptr].max = node_[(ptr << 1)].max; node_[ptr].sum = node_[ptr << 1].sum + node_[(ptr << 1) + 1].sum; } } // _downward_applyDown(ptr1): leaf[ptr1]の値を正しくする. void _downward_applyDown(int ptr1, int width = 1) { if (1 < ptr1) _downward_applyDown(ptr1 >> 1, width << 1); _applyDown(ptr1, width); } void _setValueRange(int begin, int end, T val, int ptr, int rangebegin, int rangeend) { if (rangeend <= begin || end <= rangebegin) return; // note:範囲外 if (begin <= rangebegin && rangeend <= end) { if (size_ <= ptr) { leaf_[rangebegin] = val; } else { node_[ptr].sum = val * (rangeend - rangebegin); node_[ptr].max.value = val; node_[ptr].lazyType = Cmd::Flat; node_[ptr].lazyValue = val; } return; } _applyDown(ptr, rangeend - rangebegin); _setValueRange(begin, end, val, ptr << 1, rangebegin, (rangebegin + rangeend) >> 1); _setValueRange(begin, end, val, (ptr << 1) + 1, (rangebegin + rangeend) >> 1, rangeend); _applyUp(ptr); } void _addValueRange(int begin, int end, T val, int ptr, int rangebegin, int rangeend) { if (rangeend <= begin || end <= rangebegin) return; // note:範囲外 if (begin <= rangebegin && rangeend <= end) { if (size_ <= ptr) { leaf_[rangebegin] += val; } else { node_[ptr].sum += val * (rangeend - rangebegin); node_[ptr].max.value += val; node_[ptr].lazyValue += val; if (node_[ptr].lazyType == Cmd::None) node_[ptr].lazyType = Cmd::Add; } return; } _applyDown(ptr, rangeend - rangebegin); _addValueRange(begin, end, val, ptr << 1, rangebegin, (rangebegin + rangeend) >> 1); _addValueRange(begin, end, val, (ptr << 1) + 1, (rangebegin + rangeend) >> 1, rangeend); _applyUp(ptr); } T _getSumRange(int begin, int end, int ptr, int rangebegin, int rangeend) { if (rangeend <= begin || end <= rangebegin) return 0; // note:範囲外 if (begin <= rangebegin && rangeend <= end) { if (size_ <= ptr) return leaf_[rangebegin]; else return node_[ptr].sum; } _applyDown(ptr, rangeend - rangebegin); return _getSumRange(begin, end, ptr << 1, rangebegin, (rangebegin + rangeend) >> 1) + _getSumRange(begin, end, (ptr << 1) + 1, (rangebegin + rangeend) >> 1, rangeend); } IdxVal _getMaxRange(int begin, int end, int ptr, int rangebegin, int rangeend) { if (rangeend <= begin || end <= rangebegin) return IdxVal(-1); // note:範囲外 if (begin <= rangebegin && rangeend <= end) { if (size_ <= ptr) return IdxVal(rangebegin, leaf_[rangebegin]); else return node_[ptr].max; } _applyDown(ptr, rangeend - rangebegin); auto l = _getMaxRange(begin, end, ptr << 1, rangebegin, (rangebegin + rangeend) >> 1); auto r = _getMaxRange(begin, end, (ptr << 1) + 1, (rangebegin + rangeend) >> 1, rangeend); if (l.index == -1) return move(r); if (r.index == -1) return move(l); return l.value < r.value ? move(r) : move(l); } public: // [index] の値を求める inline T getValue(int index) { _downward_applyDown((index + size_) >> 1); return leaf_[index]; } // [index] の値を書き換える inline void setValue(int index, T val) { _downward_applyDown((index + size_) >> 1); T diff = val - leaf_[index]; leaf_[index] = val; for (int ptr = (index + size_); 1 < ptr;) { ptr >>= 1; node_[ptr].sum -= diff; _applyUp(ptr); } } // [index] の値に加算する inline void addValue(int index, T val) { _downward_applyDown((index + size_) >> 1); leaf_[index] += val; for (int ptr = (index + size_); 1 < ptr;) { ptr >>= 1; node_[ptr].sum += val; _applyUp(ptr); } } // 区間[begin,end)全てにvalをセットする inline void setValueRange(int begin, int end, T val) { _setValueRange(begin, end, val, 1, 0, size_); } // 区間[begin,end)に一様にvalを加算する inline void addValueRange(int begin, int end, T val) { _addValueRange(begin, end, val, 1, 0, size_); } // 区間[begin,end)の和を求める inline T getSumRange(int begin, int end) { return _getSumRange(begin, end, 1, 0, size_); } // 区間[begin,end)の最大値とその位置を求める inline IdxVal getMaxRange(int begin, int end) { return _getMaxRange(begin, end, 1, 0, size_); } }; // // int main() { int N; scanner >> N; SegmentTree<ll> seg(N); repeat(i, N) { ll a; scanner >> a; seg.setValue(i, -a); } int q; scanner >> q; repeat(_, q) { int k,l,r,c; scanner >> k >> l >> r >> c; if (k == 1) { seg.addValueRange(l-1, r, -c); } if (k == 2) { auto p = seg.getMaxRange(l-1, r); printer << -p.value << '\n'; } } return 0; }