結果
問題 | No.876 Range Compress Query |
ユーザー | mai |
提出日時 | 2019-09-06 22:21:37 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 124 ms / 2,000 ms |
コード長 | 15,495 bytes |
コンパイル時間 | 4,472 ms |
コンパイル使用メモリ | 241,272 KB |
実行使用メモリ | 9,472 KB |
最終ジャッジ日時 | 2024-06-24 19:35:17 |
合計ジャッジ時間 | 6,370 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,376 KB |
testcase_05 | AC | 2 ms
5,376 KB |
testcase_06 | AC | 2 ms
5,376 KB |
testcase_07 | AC | 2 ms
5,376 KB |
testcase_08 | AC | 2 ms
5,376 KB |
testcase_09 | AC | 2 ms
5,376 KB |
testcase_10 | AC | 2 ms
5,376 KB |
testcase_11 | AC | 121 ms
9,344 KB |
testcase_12 | AC | 100 ms
9,344 KB |
testcase_13 | AC | 103 ms
9,472 KB |
testcase_14 | AC | 119 ms
9,344 KB |
testcase_15 | AC | 84 ms
9,344 KB |
testcase_16 | AC | 117 ms
9,344 KB |
testcase_17 | AC | 119 ms
9,344 KB |
testcase_18 | AC | 124 ms
9,344 KB |
ソースコード
#pragma GCC optimize ("O3") #pragma GCC target ("avx") #include "bits/stdc++.h" using namespace std; using ll = long long int; #define debugos cout #define debug(v) {printf("L%d %s > ",__LINE__,#v);debugos<<(v)<<endl;} #define debugv(v) {printf("L%d %s > ",__LINE__,#v);for(auto e:(v)){debugos<<e<<" ";}debugos<<endl;} #define debuga(m,w) {printf("L%d %s > ",__LINE__,#m);for(int x=0;x<(w);x++){debugos<<(m)[x]<<" ";}debugos<<endl;} #define debugaa(m,h,w) {printf("L%d %s >\n",__LINE__,#m);for(int y=0;y<(h);y++){for(int x=0;x<(w);x++){debugos<<(m)[y][x]<<" ";}debugos<<endl;}} #define all(v) (v).begin(),(v).end() #define repeat(cnt,l) for(auto cnt=remove_reference<decltype(l)>::type();(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 ll MD = 1000000007ll; const long double PI = 3.1415926535897932384626433832795L; inline void assert_call(bool assertion, function<void()> f) { if (!assertion) { cerr << "assertion fault:" << endl; f(); abort(); } } template<typename T1, typename T2> inline ostream& operator <<(ostream &o, const pair<T1, T2> p) { o << '(' << p.first << ':' << p.second << ')'; return o; } template<typename Vec> inline ostream& _ostream_vecprint(ostream& os, const Vec& a) { os << '['; for (const auto& e : a) os << ' ' << e << ' '; os << ']'; return os; } template<typename T> inline ostream& operator<<(ostream& o, const vector<T>& v) { return _ostream_vecprint(o, v); } template<typename T, size_t S> inline ostream& operator<<(ostream& o, const array<T, S>& v) { return _ostream_vecprint(o, v); } 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); } #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 #define isvisiblechar(c) (0x21<=(c)&&(c)<=0x7E) class MaiScanner { FILE* fp_; 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_); } inline MaiScanner& operator>>(int& var) noexcept { input_integer<int>(var); return *this; } inline MaiScanner& operator>>(long long& var) noexcept { input_integer<long long>(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; } inline MaiPrinter& operator<<(int var) noexcept { output_integer<int>(var); return *this; } inline MaiPrinter& operator<<(long long var) noexcept { output_integer<long long>(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 N, Q; // int main() { scanner >> N >> Q; SegmentTree<int> segv(N); SegmentTree<int> segd(N); int la; repeat(i, N) { int a; scanner >> a; segv.setValue(i, a); if (0 < i) segd.setValue(i-1, la != a); la = a; } repeat(_, Q) { int a,b,c,d; scanner >> a; if (a == 1) { scanner >> b >> c >> d; --b; --c; segv.addValueRange(b, c+1, d); if (0 < b) segd.setValue(b-1, segv.getValue(b-1) != segv.getValue(b)); if (c < N-1) segd.setValue(c, segv.getValue(c) != segv.getValue(c+1)); } else { scanner >> b >> c; --b; --c; int x = segd.getSumRange(b, c)+1; printer << x << '\n'; } } return 0; }