質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

1071閲覧

Range Update Query 時間超過を解決したい

退会済みユーザー

退会済みユーザー

総合スコア0

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/04/28 12:14

編集2021/04/28 12:24

AOJのRUQのジャッジで時間超過しました。
この問題を解決したいです。

該当のソースコード

c++

1#include <iostream> 2#include <vector> 3using namespace std; 4 5#define INF 2147483647 6 7vector<int> node; 8int N; 9 10void update(int s, int t, int x) { 11 s += N - 1; 12 t += N - 1; 13 14 //cout << "update s = " << s << " t = " << t << endl; 15 16 while(s <= t){ 17 //cout << s << endl; 18 node[s] = x; 19 s++; 20 } 21 22} 23 24 25int find(int i) { 26 //cout << "find " << i + N - 1 << endl; 27 return node[i + N - 1]; 28} 29 30 31 32int main() { 33 34 int n, q; 35 cin >> n >> q; 36 N = 1; 37 38 while (N < n) N *= 2; 39 40 node = vector<int>(2 * N - 1, INF); 41 42 for (int j = 0; j < q; j++) { 43 44 int com; 45 cin >> com; 46 47 if (com == 0) { 48 int s, t, x; 49 cin >> s >> t >> x; 50 update(s, t, x); 51 } 52 53 else { 54 int i; 55 cin >> i; 56 cout << find(i) << endl; 57 } 58 } 59 return 0; 60}

AOJ:case14で時間超過しました

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

単なる配列では無理なので、何らかのデータ構造を駆使する必要があります。

vectorのサイズの計算からして、セグメント木を使おうとしていたと思われるので、
セグメント木の応用による解法を示します。
(AOJには登録していないのでTLEが解消できるかまでは確認できていません)

更新時に範囲内の個々の数値を全て書き換えるのは大変なので、
範囲を代表する値(セグメント木のノード)を1つ書き換えるだけですまそうというアイデアです。

当然範囲内の値がばらばらの場合もあるので、そのような場合は-1を保存するというルールとします。

このようなルールにしておけば、findについては、
根から葉までたどって、-1以外が出てきたらその値を返すだけで実装できます。

updateは、根から葉までたどって、自ノードの範囲が更新範囲外なら何もしない、
自ノードの範囲が更新範囲に完全に含まれるなら自ノードの値を更新、
そうでなければ子ノードをupdateする感じです。

子ノードをupdateする際に、自ノードに-1以外の値が設定されていたら、
範囲内の値がすべて同じという前提が崩れるので、
子ノードに自ノードの値をコピーしたうえで自ノードを-1に更新します。

C++

1void update(int s, int t, int x, int k = 0, int l = 0, int r = N - 1) { 2 if (t < l || r < s) 3 return; 4 if (s <= l && r <= t) { 5 node[k] = x; 6 return; 7 } 8 if (node[k] >= 0) { 9 node[k * 2 + 1] = node[k]; 10 node[k * 2 + 2] = node[k]; 11 node[k] = -1; 12 } 13 int m = (l + r + 1) / 2; 14 update(s, t, x, k * 2 + 1, l, m - 1); 15 update(s, t, x, k * 2 + 2, m, r); 16} 17 18 19int find(int i) { 20 int k = 0, l = 0, r = N - 1; 21 while (node[k] < 0) { 22 int m = (l + r + 1) / 2; 23 if (i < m) { 24 r = m - 1; 25 k = k * 2 + 1; 26 } 27 else { 28 l = m; 29 k = k * 2 + 2; 30 } 31 } 32 return node[k]; 33}

投稿2021/04/30 21:27

actorbug

総合スコア2429

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問