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

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

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

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

Q&A

解決済

1回答

562閲覧

out of range18446744073709551615の治し方

runa17

総合スコア3

C++

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

0グッド

1クリップ

投稿2022/12/23 13:08

c++

1#include <bits/stdc++.h> 2using namespace std; 3 4int main(){ 5 int n,q; 6 cin>>n>>q; 7 vector<int> x(n),y(n); 8 for(int i=0; i<n; i++){cin>>x.at(i); y.at(i)=y.at(i-1)+x.at(i); } 9 for(int i=0; i<n; i++){ 10 int l,r; 11 cin>>l>>r; 12 cout<<y.at(r-1)-y.at(l-1)<<endl; 13 } 14 }

このコードを実行しようとすると

[Wandbox] Start
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check: __n (which is 18446744073709551615) >= this->size() (which is 10)
[Signal] Aborted
[Wandbox] Finish

と出てエラーになってしまうのですが何故なのかわかりません
・18446744073709551615という数字はどこから来ているか?
・エラーが出ないようにするにはどうすればいいのか?
を教えてください
問題は競技プログラミンングの鉄則の演習問題A06です

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

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

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

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

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

knuser

2022/12/23 13:17

問題が提示されていないため回答が提示しづらいですが、`18446744073709551615`は、正の整数が期待されるsize_tの箇所に、負の値(-1)を指定しているため発生しているのではないかと思います。 少なくとも`y.at(i-1)`はi = 0の場合に負の値になりそうですが、意図した挙動でしょうか?
guest

回答1

0

ベストアンサー

out_of_range について

エラー文に出てくるout_of_rangeは、「範囲外参照」を表すエラーです。

例えば、vector<int> a(3)(3個の要素を持つ配列)を用意した後に、a[3](配列の4番目の要素)にアクセスしようとするとこのエラーが発生します。

C++

1for(int i=0; i<n; i++){ 2 cin>>x.at(i); 3 y.at(i)=y.at(i-1)+x.at(i); //ココ 4}

上記のコードでは、for文の1回目のループで i は0であり、そうするとy.at(i-1)y[-1]という意味になります。勿論そのような要素はありませんから、ここでエラーが発生します。
(.at()の引数は unsigned long long 型(非負整数)なので、int 型の -1 を unsigned long long 型に強制的に型変換すると、18446744073709551615 = 2の64乗-1 になります)

累積和を使う解き方について

今回のように累積和を使って解く問題では、累積和の配列の先頭に0を追加するのが普通です。言い換えると、便宜的に「0日目までに合計0人来場」を追加するという感じです。
1日目までの累積和→配列の2番目、2日目まで→3番目、... というふうに、配列の要素が1つずつずれるので注意してください。

こうすると、1日目までの累積和を求めるときも、「0日目までの累積和」が配列にちゃんと含まれているので、エラーは発生しません。

C++

1vector<int> x(n),y(n+1); //yの要素数を1増やして、 2y[0]=0; //先頭の要素に0を代入 3for(int i=0; i<n; i++){ 4 cin>>x.at(i); 5 y.at(i+1)=y.at(i)+x.at(i); //yは要素が1つずつずれるので、i→i+1, i-1→i となる 6}

次に、「L日目からR日目までの来場者数」を求めるには、「R日目までの累積和」から「L-1日目までの累積和」を引く必要があることに注意してください。
このときも L==1 のとき「0日目までの累積和」が必要ですが、配列に含まれているため問題なく計算できます。

最後に、2つ目のfor文の範囲をi<nからi<qに直しましょう。

C++

1for(int i=0; i<q; i++){ //for文の範囲に注意 2 int l,r; 3 cin>>l>>r; 4 cout<<y.at(r)-y.at(l-1)<<endl; //「R日目までの累積和」は配列のR+1番目 = y[r] 5 //「L-1日目までの累積和」は配列のL番目 = y[l-1] 6}

投稿2022/12/24 03:40

luuguas

総合スコア492

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

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

runa17

2022/12/24 03:43

治りました!ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問