結果
問題 | No.880 Yet Another Segment Tree Problem |
ユーザー | tonegawa |
提出日時 | 2023-09-28 21:01:39 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 14,429 bytes |
コンパイル時間 | 1,772 ms |
コンパイル使用メモリ | 150,156 KB |
実行使用メモリ | 18,088 KB |
最終ジャッジ日時 | 2024-07-21 15:50:34 |
合計ジャッジ時間 | 13,807 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,812 KB |
testcase_01 | AC | 3 ms
5,376 KB |
testcase_02 | AC | 3 ms
5,376 KB |
testcase_03 | AC | 3 ms
5,376 KB |
testcase_04 | AC | 3 ms
5,376 KB |
testcase_05 | AC | 3 ms
5,376 KB |
testcase_06 | AC | 2 ms
5,376 KB |
testcase_07 | AC | 3 ms
5,376 KB |
testcase_08 | AC | 3 ms
5,376 KB |
testcase_09 | AC | 3 ms
5,376 KB |
testcase_10 | AC | 3 ms
5,376 KB |
testcase_11 | AC | 281 ms
11,008 KB |
testcase_12 | AC | 271 ms
11,136 KB |
testcase_13 | AC | 190 ms
10,912 KB |
testcase_14 | AC | 263 ms
11,136 KB |
testcase_15 | AC | 285 ms
11,136 KB |
testcase_16 | AC | 309 ms
11,136 KB |
testcase_17 | AC | 250 ms
11,204 KB |
testcase_18 | AC | 240 ms
11,264 KB |
testcase_19 | AC | 108 ms
11,164 KB |
testcase_20 | AC | 109 ms
11,192 KB |
testcase_21 | AC | 111 ms
11,068 KB |
testcase_22 | AC | 108 ms
11,136 KB |
testcase_23 | AC | 114 ms
11,136 KB |
testcase_24 | AC | 90 ms
10,996 KB |
testcase_25 | AC | 93 ms
11,136 KB |
testcase_26 | AC | 92 ms
11,132 KB |
testcase_27 | AC | 89 ms
11,008 KB |
testcase_28 | AC | 93 ms
11,088 KB |
testcase_29 | AC | 262 ms
11,264 KB |
testcase_30 | AC | 285 ms
11,172 KB |
testcase_31 | AC | 305 ms
11,128 KB |
testcase_32 | AC | 69 ms
11,264 KB |
testcase_33 | TLE | - |
testcase_34 | -- | - |
testcase_35 | -- | - |
testcase_36 | -- | - |
testcase_37 | -- | - |
ソースコード
#line 1 ".lib/template.hpp" #include <iostream> #include <string> #include <vector> #include <array> #include <tuple> #include <stack> #include <queue> #include <deque> #include <algorithm> #include <set> #include <map> #include <unordered_set> #include <unordered_map> #include <bitset> #include <cmath> #include <functional> #include <cassert> #include <climits> #include <iomanip> #include <numeric> #include <memory> #include <random> #include <thread> #include <chrono> #define allof(obj) (obj).begin(), (obj).end() #define range(i, l, r) for(int i=l;i<r;i++) #define unique_elem(obj) obj.erase(std::unique(allof(obj)), obj.end()) #define bit_subset(i, S) for(int i=S, zero_cnt=0;(zero_cnt+=i==S)<2;i=(i-1)&S) #define bit_kpop(i, n, k) for(int i=(1<<k)-1,x_bit,y_bit;i<(1<<n);x_bit=(i&-i),y_bit=i+x_bit,i=(!i?(1<<n):((i&~y_bit)/x_bit>>1)|y_bit)) #define bit_kth(i, k) ((i >> k)&1) #define bit_highest(i) (i?63-__builtin_clzll(i):-1) #define bit_lowest(i) (i?__builtin_ctzll(i):-1) #define sleepms(t) std::this_thread::sleep_for(std::chrono::milliseconds(t)) using ll = long long; using ld = long double; using ul = uint64_t; using pi = std::pair<int, int>; using pl = std::pair<ll, ll>; using namespace std; template<typename F, typename S> std::ostream &operator<<(std::ostream &dest, const std::pair<F, S> &p){ dest << p.first << ' ' << p.second; return dest; } template<typename T> std::ostream &operator<<(std::ostream &dest, const std::vector<std::vector<T>> &v){ int sz = v.size(); if(sz==0) return dest; for(int i=0;i<sz;i++){ int m = v[i].size(); for(int j=0;j<m;j++) dest << v[i][j] << (i!=sz-1&&j==m-1?'\n':' '); } return dest; } template<typename T> std::ostream &operator<<(std::ostream &dest, const std::vector<T> &v){ int sz = v.size(); if(sz==0) return dest; for(int i=0;i<sz-1;i++) dest << v[i] << ' '; dest << v[sz-1]; return dest; } template<typename T, size_t sz> std::ostream &operator<<(std::ostream &dest, const std::array<T, sz> &v){ if(sz==0) return dest; for(int i=0;i<sz-1;i++) dest << v[i] << ' '; dest << v[sz-1]; return dest; } template<typename T> std::ostream &operator<<(std::ostream &dest, const std::set<T> &v){ for(auto itr=v.begin();itr!=v.end();){ dest << *itr; itr++; if(itr!=v.end()) dest << ' '; } return dest; } template<typename T, typename E> std::ostream &operator<<(std::ostream &dest, const std::map<T, E> &v){ for(auto itr=v.begin();itr!=v.end();){ dest << '(' << itr->first << ", " << itr->second << ')'; itr++; if(itr!=v.end()) dest << '\n'; } return dest; } std::ostream &operator<<(std::ostream &dest, __int128_t value) { std::ostream::sentry s(dest); if (s) { __uint128_t tmp = value < 0 ? -value : value; char buffer[128]; char *d = std::end(buffer); do { --d; *d = "0123456789"[tmp % 10]; tmp /= 10; } while (tmp != 0); if (value < 0) { --d; *d = '-'; } int len = std::end(buffer) - d; if (dest.rdbuf()->sputn(d, len) != len) { dest.setstate(std::ios_base::badbit); } } return dest; } template<typename T> vector<T> make_vec(size_t sz, T val){return std::vector<T>(sz, val);} template<typename T, typename... Tail> auto make_vec(size_t sz, Tail ...tail){ return std::vector<decltype(make_vec<T>(tail...))>(sz, make_vec<T>(tail...)); } template<typename T> vector<T> read_vec(size_t sz){ std::vector<T> v(sz); for(int i=0;i<(int)sz;i++) std::cin >> v[i]; return v; } template<typename T, typename... Tail> auto read_vec(size_t sz, Tail ...tail){ auto v = std::vector<decltype(read_vec<T>(tail...))>(sz); for(int i=0;i<(int)sz;i++) v[i] = read_vec<T>(tail...); return v; } void io_init(){ std::cin.tie(nullptr); std::ios::sync_with_stdio(false); } #line 2 "a.cpp" template<typename beats_struct> struct segment_tree_beats{ using Val = typename beats_struct::Val; using Lazy = typename beats_struct::Lazy; int N, M; std::vector<Val> val; std::vector<Lazy> lazy; std::vector<bool> is_id; void push_down(int k, int l, int r){ if(M - 1 <= k || is_id[k]) return; int mid = (l + r) >> 1; propagate(k * 2 + 1, l, mid, lazy[k]); propagate(k * 2 + 2, mid, r, lazy[k]); is_id[k] = true; } void propagate(int k, int l, int r, const Lazy &x){ if(k < M - 1){ if(is_id[k]){ lazy[k] = x; is_id[k] = false; }else{ beats_struct::propagate_lazy(lazy[k], x); } } beats_struct::apply(val[k], x, l, r); } void set(int a, Val x, int k, int l, int r){ if(r - l == 1){ val[k] = x; return; } push_down(k, l, r); int mid = (l + r) >> 1; if(a < mid) set(a, x, k * 2 + 1, l, mid); else set(a, x, k * 2 + 2, mid, r); beats_struct::merge_val(val[k], val[k * 2 + 1], val[k * 2 + 2]); } void get(int a, int k, int l, int r, Val &ans){ if(r - l == 1){ ans = val[k]; return; } push_down(k, l, r); int mid = (l + r) >> 1; if(a < mid) get(a, k * 2 + 1, l, mid, ans); else get(a, k * 2 + 2, mid, r, ans); } template<int id> void update(int a, int b, const Lazy &x, int k, int l, int r){ if(r <= a || b <= l || beats_struct::template break_check<id>(val[k], x)) return; /* if(a <= l && r <= b && beats_struct::template tag_check<id>(val[k], x)){ propagate(k, l, r, x); return; } */ if(a <= l && r <= b && beats_struct::template tag_check<id>(val[k], x)){ if(id == 0){ propagate(k, l, r, x); }else{ Lazy y(std::gcd(val[k].unique, x.setx)); propagate(k, l, r, y); } return; } push_down(k, l, r); update<id>(a, b, x, k * 2 + 1, l, (l + r) / 2); update<id>(a, b, x, k * 2 + 2, (l + r) / 2, r); beats_struct::merge_val(val[k], val[k * 2 + 1], val[k * 2 + 2]); } void query(int a, int b, int k, int l, int r, Val &ans){ if(r <= a || b <= l) return; if(a <= l && r <= b){ Val tmp = beats_struct::id_val(); beats_struct::merge_val(tmp, ans, val[k]); ans = tmp; return; } push_down(k, l, r); query(a, b, k * 2 + 1, l, (l + r) / 2, ans); query(a, b, k * 2 + 2, (l + r) / 2, r, ans); } int c2(int x){ int y = 1; while(y < x) y <<= 1; return y; } segment_tree_beats(): N(0), M(0){} template<typename T> segment_tree_beats(const std::vector<T> &v): N(v.size()), M(c2(N)), val(2 * M - 1, Val()), lazy(M - 1, Lazy()), is_id(M - 1, true){ for(int i = 0; i < N; i++) val[M - 1 + i] = Val(v[i]); for(int i = N; i < M; i++) val[M - 1 + i] = beats_struct::id_val(); for(int i = M - 2; i >= 0; i--) beats_struct::merge_val(val[i], val[i * 2 + 1], val[i * 2 + 2]); } template<int id> void update(int l, int r, Lazy x){ update<id>(l, r, x, 0, 0, M); } Val query(int l, int r){ Val ans = beats_struct::id_val(); query(l, r, 0, 0, M, ans); return ans; } }; template<typename T> struct add_chmin_chmax{ static constexpr T inf = std::numeric_limits<T>::max(); static constexpr T minf = std::numeric_limits<T>::min(); struct Val{ T min, second_min, max, second_max, sum; int min_cnt, max_cnt; Val(): min(inf), second_min(inf), max(minf), second_max(minf), sum(0), min_cnt(0), max_cnt(0){} Val(T x): min(x), second_min(inf), max(x), second_max(minf), sum(x), min_cnt(1), max_cnt(1){} }; struct Lazy{ T add, lower, upper; Lazy(): add(0), lower(minf), upper(inf){} Lazy(T a, T b, T c): add(a), lower(b), upper(c){} }; static Val id_val(){ return Val(); } // l, rをマージしてvに代入 static void merge_val(Val &v, const Val &l, const Val &r){ v.sum = l.sum + r.sum; if(l.max == r.max){ v.max = l.max; v.max_cnt = l.max_cnt + r.max_cnt; v.second_max = std::max(l.second_max, r.second_max); }else if(l.max > r.max){ v.max = l.max; v.max_cnt = l.max_cnt; v.second_max = std::max(l.second_max, r.max); }else{ v.max = r.max; v.max_cnt = r.max_cnt; v.second_max = std::max(l.max, r.second_max); } if(l.min == r.min){ v.min = l.min; v.min_cnt = l.min_cnt + r.min_cnt; v.second_min = std::min(l.second_min, r.second_min); }else if(l.min < r.min){ v.min = l.min; v.min_cnt = l.min_cnt; v.second_min = std::min(l.second_min, r.min); }else{ v.min = r.min; v.min_cnt = r.min_cnt; v.second_min = std::min(l.min, r.second_min); } } static void apply(Val &a, const Lazy &b, int l, int r){ if(b.add){ a.min += b.add; if(a.second_min != inf) a.second_min += b.add; a.max += b.add; if(a.second_max != minf) a.second_max += b.add; a.sum += b.add * (r - l); } if(a.min < b.lower){ a.sum += (b.lower - a.min) * a.min_cnt; if(a.second_max == a.min) a.second_max = b.lower; else if(a.max == a.min) a.max = b.lower, a.second_max = minf; a.min = b.lower; } if(b.upper < a.max){ a.sum -= (a.max - b.upper) * a.max_cnt; if(a.second_min == a.max) a.second_min = b.upper; else if(a.min == a.max) a.min = b.upper, a.second_min = inf; a.max = b.upper; } } static void propagate_lazy(Lazy &a, const Lazy &b){ if(b.add){ a.add += b.add; if(a.lower != minf) a.lower += b.add; if(a.upper != inf) a.upper += b.add; } if(a.upper <= b.lower) a.lower = a.upper = b.lower; else if(b.upper <= a.lower) a.lower = a.upper = b.upper; else{ a.lower = std::max(a.lower, b.lower); a.upper = std::min(a.upper, b.upper); } } // chmin template<int id, std::enable_if_t<id == 0>* = nullptr> static bool break_check(const Val &v, const Lazy &x){ return v.max < x.upper; } template<int id, std::enable_if_t<id == 0>* = nullptr> static bool tag_check(const Val &v, const Lazy &x){ return v.second_max < x.upper; } // chmax template<int id, std::enable_if_t<id == 1>* = nullptr> static bool break_check(const Val &v, const Lazy &x){ return v.min > x.lower; } template<int id, std::enable_if_t<id == 1>* = nullptr> static bool tag_check(const Val &v, const Lazy &x){ return v.second_min > x.lower; } // add template<int id, std::enable_if_t<id == 2>* = nullptr> static bool break_check(const Val &v, const Lazy &x){ return false; } template<int id, std::enable_if_t<id == 2>* = nullptr> static bool tag_check(const Val &v, const Lazy &x){ return true; } }; template<typename T> struct abc256ex_set_div_sum{ static constexpr T minf = std::numeric_limits<T>::min(); struct Val{ T sum, unique; // unique != minfなら区間がその値でユニーク Val(): sum(0), unique(minf){} Val(T x): sum(x), unique(x){} }; struct Lazy{ T setx; Lazy(): setx(minf){} Lazy(T x): setx(x){} /* update関数を書き換える if(a <= l && r <= b && beats_struct::template tag_check<id>(val[k], x)){ if(id == 0){ propagate(k, l, r, x); }else{ Lazy y(val[k].unique / x.setx); propagate(k, l, r, y); } return; } */ }; static Val id_val(){ return Val(); } // l, rをマージしてvに代入 static void merge_val(Val &v, const Val &l, const Val &r){ v.sum = l.sum + r.sum; if(l.unique == r.unique) v.unique = l.unique; else v.unique = minf; } static void apply(Val &a, const Lazy &b, int l, int r){ a.sum = b.setx * (r - l); a.unique = b.setx; } static void propagate_lazy(Lazy &a, const Lazy &b){ a = b; } // set template<int id, std::enable_if_t<id == 0>* = nullptr> static bool break_check(const Val &v, const Lazy &x){ return false; } template<int id, std::enable_if_t<id == 0>* = nullptr> static bool tag_check(const Val &v, const Lazy &x){ return true; } // div template<int id, std::enable_if_t<id == 1>* = nullptr> static bool break_check(const Val &v, const Lazy &x){ return v.unique == 0; } template<int id, std::enable_if_t<id == 1>* = nullptr> static bool tag_check(const Val &v, const Lazy &x){ return v.unique != minf; } }; template<typename T> struct yuki880_set_gcd_min_sum{ static constexpr T minf = std::numeric_limits<T>::min(); struct Val{ T sum, unique, max; Val(): sum(0), unique(minf), max(minf){} Val(T x): sum(x), unique(x), max(x){} }; struct Lazy{ T setx; Lazy(): setx(minf){} Lazy(T x): setx(x){} /* update関数を書き換える if(a <= l && r <= b && beats_struct::template tag_check<id>(val[k], x)){ if(id == 0){ propagate(k, l, r, x); }else{ Lazy y(gcd(val[k].unique, x.setx)); propagate(k, l, r, y); } return; } */ }; static Val id_val(){ return Val(); } // l, rをマージしてvに代入 static void merge_val(Val &v, const Val &l, const Val &r){ v.sum = l.sum + r.sum; v.max = std::max(l.max, r.max); if(l.unique == r.unique) v.unique = l.unique; else v.unique = minf; } static void apply(Val &a, const Lazy &b, int l, int r){ a.sum = b.setx * (r - l); a.max = b.setx; a.unique = b.setx; } static void propagate_lazy(Lazy &a, const Lazy &b){ a = b; } // set template<int id, std::enable_if_t<id == 0>* = nullptr> static bool break_check(const Val &v, const Lazy &x){ return false; } template<int id, std::enable_if_t<id == 0>* = nullptr> static bool tag_check(const Val &v, const Lazy &x){ return true; } // gcd template<int id, std::enable_if_t<id == 1>* = nullptr> static bool break_check(const Val &v, const Lazy &x){ return v.unique != minf && std::gcd(v.unique, x.setx) == v.unique; } template<int id, std::enable_if_t<id == 1>* = nullptr> static bool tag_check(const Val &v, const Lazy &x){ return v.unique != minf; } }; int main(){ io_init(); int n, q; std::cin >> n >> q; auto a = read_vec<ll>(n); segment_tree_beats<yuki880_set_gcd_min_sum<ll>> seg(a); for(int i = 0; i < q; i++){ long long x, y, z, v; std::cin >> x >> y >> z; y--; if(x == 3){ std::cout << seg.query(y, z).max << '\n'; }else if(x == 4){ std::cout << seg.query(y, z).sum << '\n'; }else{ std::cin >> v; if(x == 1){ seg.update<0>(y, z, {v}); }else if(x == 2){ seg.update<1>(y, z, {v}); } } } }