Submission #64734
ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | #include <bits/stdc++.h> using namespace std; vector<int64_t> b; //累積和してセグ木内で使うのでグローバルで宣言する struct LazySegmentTree{ int n, sz; vector<int64_t> node; //値配列 vector< int > lazy; //遅延配列(左端の差を格納する) int64_t e1 = 0LL; //単位元(値) int e2 = INT_MAX; //単位元(遅延) LazySegmentTree(vector<int64_t> &v){ n = v.size(); sz = 1; while (sz < n) sz <<= 1; //nを超えない最大の2羃 node.resize(sz * 2 - 1, e1); lazy.resize(sz * 2 - 1, e2); for ( int i = 0; i < n; ++i){ node[i + sz - 1] = v[i]; } for ( int i = sz - 2; i >= 0; --i){ node[i] = node[i * 2 + 1] + node[i * 2 + 2]; } } // [l, r) 半開区間で実装 void update( int l, int r, int x){ update(l, r, x, 0, 0, sz); } void update( int l, int r, int x, int k, int u, int v){ // 伝播 eval(k, u, v - 1); // 完全に被らないなら見ない if (r <= u || v <= l) return ; // 完全に被るなら遅延配列を更新し伝播 if (l <= u && v <= r){ lazy[k] = x; eval(k, u, v - 1); } else { update(l, r, x, k * 2 + 1, u, (u + v) / 2); // 左の子へ update(l, r, x, k * 2 + 2, (u + v) / 2, v); // 右の子へ node[k] = node[k * 2 + 1] + node[k * 2 + 2]; // 左右の子の更新が終わったら値配列を更新 } return ; } // [l, r) 半開区間で実装 int64_t sum( int l, int r){ return (sum(l, r, 0, 0, sz)); } int64_t sum( int l, int r, int k, int u, int v){ if (r <= u || v <= l) return (0); // 完全に被らないなら0を返す eval(k, u, v - 1); // 伝播 if (l <= u && v <= r) return (node[k]); // 完全に区間に被るなら値を返す int64_t vl = sum(l, r, k * 2 + 1, u, (u + v) / 2); // 左の子へ int64_t vr = sum(l, r, k * 2 + 2, (u + v) / 2, v); // 右の子へ return (vl + vr); } // 伝播を行う // 引数はノード番号、ノードの担当する区間の左端、区間の右端 void eval( int k, int l, int r){ // lazy[k]が単位元でない=伝播する値がある if (lazy[k] != e2){ l = l + lazy[k]; // bの左端 r = r + lazy[k]; // bの右端 node[k] = b[r] - b[l - 1]; // 値配列にbの区間和を加算 // ノードkが最下段でなければ伝播 if (k < sz - 1){ lazy[k * 2 + 1] = lazy[k]; lazy[k * 2 + 2] = lazy[k]; } lazy[k] = e2; // 伝播し終わったので単位元に戻す } return ; } }; signed main(){ cin.tie(nullptr); ios_base::sync_with_stdio( false ); int n, m; cin >> n >> m; vector<int64_t> a(n + 1); b.resize(n + 1); for ( int i = 1; i <= n; ++i){ cin >> a[i]; } for ( int i = 1; i <= n; ++i){ cin >> b[i]; b[i] += b[i-1]; } LazySegmentTree seg(a); // 配列aで初期化 for ( int i = 0; i < m; ++i){ int op; cin >> op; if (op == 0){ int x, y, z; cin >> x >> y >> z; seg.update(x, x + z, y - x); // クエリで左端の差を与える } else { int p, q; cin >> p >> q; cout << seg.sum(p, q + 1) << '\n' ; } } return (0); } |
ステータス
項目 | データ |
---|---|
問題 | 1446 - Copy&Sum |
ユーザー名 | syoribu |
投稿日時 | 2020-11-15 22:39:49 |
言語 | C++17 |
状態 | Accepted |
得点 | 12 |
ソースコード長 | 3714 Byte |
最大実行時間 | 195 ms |
最大メモリ使用量 | 17800 KB |
セット
セット | 得点 | Cases | |
---|---|---|---|
1 | ALL | 12 / 12 | * |
テストケース
ファイル名 | 状態 | 実行時間 | メモリ使用量 | # |
---|---|---|---|---|
in1 | AC | 22 ms | 600 KB |
1
|
in2 | AC | 23 ms | 612 KB |
1
|
in3 | AC | 16 ms | 8592 KB |
1
|
in4 | AC | 18 ms | 8544 KB |
1
|
in5 | AC | 20 ms | 8628 KB |
1
|
in6 | AC | 26 ms | 8460 KB |
1
|
in7 | AC | 24 ms | 8532 KB |
1
|
in8 | AC | 28 ms | 8488 KB |
1
|
in9 | AC | 19 ms | 8576 KB |
1
|
in10 | AC | 23 ms | 688 KB |
1
|
in11 | AC | 19 ms | 516 KB |
1
|
in12 | AC | 25 ms | 600 KB |
1
|
in13 | AC | 21 ms | 552 KB |
1
|
in14 | AC | 17 ms | 500 KB |
1
|
in15 | AC | 20 ms | 576 KB |
1
|
in16 | AC | 19 ms | 396 KB |
1
|
in17 | AC | 18 ms | 468 KB |
1
|
in18 | AC | 19 ms | 524 KB |
1
|
in19 | AC | 27 ms | 560 KB |
1
|
in20 | AC | 21 ms | 696 KB |
1
|
in21 | AC | 170 ms | 10712 KB |
1
|
in22 | AC | 195 ms | 12128 KB |
1
|
in23 | AC | 168 ms | 13804 KB |
1
|
in24 | AC | 180 ms | 15088 KB |
1
|
in25 | AC | 133 ms | 16376 KB |
1
|
in26 | AC | 139 ms | 17800 KB |
1
|