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

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

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

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

Q&A

4回答

641閲覧

ABC379、D問題が解けない(茶レベル)

mldo0

総合スコア1

C++

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

0グッド

1クリップ

投稿2024/11/22 10:13

編集2024/11/22 10:14

実現したいこと

リンク内容
の問題で、自分の考えたアルゴリズムは何がいけないのか知りたい。

発生している問題・分からないこと

解答を理解することはできました。しかし、自分の書いたコードではなぜ不正解になるのかが分かりません。イメージ説明

該当のソースコード

C++

1#include <bits/stdc++.h> 2using namespace std; 3#define rep(i, n) for (int i = 0; i < n; ++i) 4#define ll long long 5 6int main() { 7 ll Q; 8 cin >> Q; 9 vector<vector<ll>> vec(Q, vector<ll>(2)); 10 vector<pair<ll, ll>> pot(1, {0, 0}); 11 12 rep(i, Q) { 13 cin >> vec[i][0]; 14 15 if (vec[i][0] == 1) { 16 if (i != 0 && vec[i - 1][0] == 2) { 17 pot.push_back({0, 0}); 18 } 19 else if (pot.empty()) { 20 pot.push_back({0, 0}); 21 } 22 pot.back().first++; 23 } 24 else if (vec[i][0] == 2) { 25 cin >> vec[i][1]; 26 if (!pot.empty()) pot.back().second += vec[i][1]; 27 } 28 else if (vec[i][0] == 3) { 29 cin >> vec[i][1]; 30 if (pot.empty()) { 31 cout << 0 << endl; 32 continue; 33 } 34 35 ll height = 0, ans = 0; 36 bool harvested = false; 37 38 for (ll j = pot.size() - 1; j >= 0; j--) { 39 height += pot[j].second; 40 if (height >= vec[i][1]) { 41 for (int k = 0; k <= j; k++) { 42 ans += pot[k].first; 43 } 44 cout << ans << endl; 45 pot.erase(pot.begin(), pot.begin() + j + 1); 46 harvested = true; 47 break; 48 } 49 } 50 51 if (!harvested) { 52 cout << 0 << endl; 53 } 54 } 55 } 56 57 return 0; 58} 59

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

ChatGPTに聞いたり、デバッグ文字を追加して状況を逐一調べたりしましたが、入力例ではすべてうまくいっていて、何がいけないのかわかりません。

補足

特になし

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

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

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

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

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

fana

2024/11/26 00:44 編集

> 自分の考えたアルゴリズムは何がいけないのか という話をしたい(:「アルゴリズムあるいはその実装たるコードのここがこう間違ってるよ」みたいな話が欲しい)のであれば, なにはともあれ「自分の考えたアルゴリズム」の内容というのを他者にわかるように説明した方が,そういう方向に話が行きやすくなるんじゃないかと思いますが,どうなんでしょうね?
guest

回答4

0

たぶんほかの人の回答もあったほうが参考になると思うので、(というか、個人的に書きたかったので)書いてみました。
c++言語があまりよくわからなくて、競技プログラミング避けていたんですが、結構問題見たときに面白いなと思ってチャレンジしてみました。

難しい型とかはわからないので、最低限vectoerだけ勉強して書きました。(queue操作がやりづらかったが)

TODOが残ってますが、考え方として特に清書せずに残しました。
intだとオーバーフローするかもしれないですが、そこらへんは定義域を見て調整すればよいと思いました。

c++

1#include <bits/stdc++.h> 2using namespace std; 3#define rep(i, n) for (int i = 0; i < n; ++i) 4#define ll long long 5 6int inputQ() { 7 int Q; 8 cin >> Q; 9 return Q; 10} 11 12vector<vector<int>> inputTable(int Q) { 13 14 vector<vector<int>> table(Q, vector<int>(2, 0)); 15 16 int inputInt1, inputInt2; 17 18 for (int i = 0; i < Q; ++i) { 19 cin >> inputInt1; 20 table[i][0] = inputInt1; 21 // 2, 3 の場合は追加で入力を受け付ける 22 if (inputInt1 == 2 || inputInt1 == 3) cin >> inputInt2, table[i][1] = inputInt2; 23 } 24 25 26 return table; 27 28} 29 30int main() { 31 int Q; 32 Q = inputQ(); 33 34 vector<vector<int>> table(Q, vector<int>(2, 0)); 35 table = inputTable(Q); 36 37 // 入力のprint debug 38 // for (int i = 0; i < table.size(); i ++) { 39 // for (int j = 0; j < table[i].size(); j ++) { 40 // cout << table[i][j]; 41 // } 42 // cout << endl; 43 // } 44 45 // return 0; 46 47 // キュー構造として考える 48 vector<vector<int>> storage(0, vector<int>(2, 0)); 49 50 51 // TODO 1が何回続いたかを記録する 52 // TODO 2が起きた回数を加算する 53 // TODO 3が起きたら後ろから配列を消す resize(n)メソッドを使用する 54 for (int i = 0; i < Q; ++i) { 55 int tag = table[i][0]; 56 57 // Memo: switchを使うと変数のスコープの挙動でエラーを吐く 58 if (tag == 1) { 59 // 初回の種植え、または、育った種がすでにあったら、先頭に新しいものを用意する 60 if (storage.size() <= 0 || storage[0][1] > 0) storage.insert(storage.begin(), {0, 0}); 61 // 埋められた回数を記録する 62 storage[0][0] = storage[0][0] + 1; 63 } else if (tag == 2) { 64 int T = table[i][1]; 65 // 各埋められた回数の横に、高さを記録する 66 for (int j = 0; j < storage.size(); ++j) { 67 storage[j][1] = T; 68 } 69 } else if (tag == 3) { 70 int H = table[i][1]; 71 int result = 0; 72 for (int j = storage.size() - 1; j >= 0; -- j) { 73 if (H <= storage[j][1]) { 74 result = result + storage[j][0]; 75 storage.resize(j); 76 } else { 77 // O(N)のためbreakしなくても遅くはない 78 break; 79 } 80 } 81 82 cout << result << endl; 83 } 84 } 85 86 // vector<vector<ll>> vec(Q, vector<ll>(2)); 87 // vector<pair<ll, ll>> pot(1, {0, 0}); 88 89 // rep(i, Q) { 90 // cin >> vec[i][0]; 91 92 // if (vec[i][0] == 1) { 93 // if (i != 0 && vec[i - 1][0] == 2) { 94 // pot.push_back({0, 0}); 95 // } 96 // else if (pot.empty()) { 97 // pot.push_back({0, 0}); 98 // } 99 // pot.back().first++; 100 // } 101 // else if (vec[i][0] == 2) { 102 // cin >> vec[i][1]; 103 // if (!pot.empty()) pot.back().second += vec[i][1]; 104 // } 105 // else if (vec[i][0] == 3) { 106 // cin >> vec[i][1]; 107 // if (pot.empty()) { 108 // cout << 0 << endl; 109 // continue; 110 // } 111 112 // ll height = 0, ans = 0; 113 // bool harvested = false; 114 115 // for (ll j = pot.size() - 1; j >= 0; j--) { 116 // height += pot[j].second; 117 // if (height >= vec[i][1]) { 118 // for (int k = 0; k <= j; k++) { 119 // ans += pot[k].first; 120 // } 121 // cout << ans << endl; 122 // pot.erase(pot.begin(), pot.begin() + j + 1); 123 // harvested = true; 124 // break; 125 // } 126 // } 127 128 // if (!harvested) { 129 // cout << 0 << endl; 130 // } 131 // } 132 // } 133 134 return 0; 135}

投稿2024/11/25 17:06

utm.

総合スコア378

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

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

utm.

2024/11/25 17:30

解説の方法は思いつかないですね。 合計の成長数と植えたときの成長数を引けばその間にどのくらい成長したかわかるってやつですよね。 なんか記憶の片隅にマンションが題材の問題で見た気がしますが、思いつかない自信しかないですね。
fana

2024/11/26 00:53

本件は > 自分の考えたアルゴリズムは何がいけないのか知りたい とかいう話になっているのですが,それに対してこの回答というのは 「質問者と同じアルゴリズム を実装してみたつもり」という内容であるのか, 「(質問文に提示されているコードとは無関係に)個人的に解いてみたよ」という話であるのか どちらなのでしょう? ……っていう意味合いが明言されていた方が参考にしやすいのではないか,とか思いました.
utm.

2024/11/27 07:20

後者です。
guest

0

1の処理で、新しい経過日数の異なるpotを追加する条件が
potが無いときと
直前の処理が2の処理の時になっていますが、
直前の処理だけでなく、前回の新しいpot用意してから今までに2の処理があった場合になると思います。
(例 直前の処理が3の場合、刈り取った後の最新potは経過日数が0でない場合もあります)

さかのぼってチェックするのは面倒なのでシンプルに
その条件をpotが無いときと最新のpotの経過日数が0以外であるならで代用できないでしょうか?
16行目(1の処理)

C++

1if ( pot.empty() ) { 2 pot.push_back({0, 0}); 3} else if(pot.back().second!=0){ 4 pot.push_back({0, 0}); 5} 6pot.back().first++;

投稿2024/11/26 03:01

編集2024/11/26 03:07
tmp

総合スコア309

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

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

0

1 : 植物が植えられていない植木鉢を
1 個用意し、その植木鉢に植物を植える。このとき植物の高さは
0 である。
2 T :
T 日待つ。このとき植えてあるすべての植物の高さが
T 増加する。
3 H : 高さが
H 以上の植物をすべて収穫し、収穫した植物の数を出力する。収穫した植物は植木鉢から取り除かれる。

つまり

"1" だったら pot に 1 つ追加
"2" だったら pot 内の全ての高さに T を加算
"3" だったら pot 内の全ての高さを調べて H 以上のものを数えて表示/削除

ですので、 vec みたいに過去のクエリを覚えておく必要も無ければ pot の first も必要無いのではないでしょうか。

書いてから解説を見ましたらベタだと時間かかるので区間を加算しておくヤツ(名前忘れた)にするんですね、失礼しました。

投稿2024/11/23 12:08

編集2024/11/23 12:14
jimbe

総合スコア13235

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

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

0

入力例ではすべてうまくいっていて、何がいけないのかわかりません。

とのことなので、うまくいかない入力例を挙げておきます。こちらの入力例でデバッグしてみてください。

以下の入力例について

5 1 2 1 3 2 1 3 1

正しい出力は以下ですが

0 1

ご提示のコードだと以下が出力されます。

0 2

上記入力例に対処すれば、AtCoder上では正答扱いになりますが、実際には時間超過が発生する可能性が残っています。
ご提示のコードに以下のような入力を与えると、収穫1回ごとに38行目で50,000回のループが発生し、収穫が100,000回行われるので、全体で5,000,000,000回の処理が行われることになります。対処方法については解説に載っている通りなので、そちらを参照してください。

200000 1 2 1 (上記2行を50,000回繰り返し) 3 50001 (上記1行を100,000回繰り返し)

投稿2024/11/22 13:59

編集2024/11/23 22:48
actorbug

総合スコア2460

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.34%

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

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

質問する

関連した質問