実現したいこと
計算量が異なる理由を知りたい。
前提
AtCoderのABC376、C問題を解いていました。リンク内容
自分の作成したコードと、回答は実装しようとしていることは同じはずなのですが、
計算量に差があります。
発生している問題・エラーメッセージ
以下の二つのコードの計算量が異なる理由を知りたいです。
該当のソースコード
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 int N; 8 9 cin >> N; 10 11 12 vector<ll> A(N); 13 vector<ll> B(N - 1); 14 15 rep(i, N){ 16 cin >> A[i]; 17 18 } 19 20 rep(i, N - 1){ 21 cin >> B[i]; 22 23 } 24 25 sort(A.begin(), A.end()); 26 27 vector<ll> D = B; 28 D.push_back(1 << 30); 29 sort(D.begin(), D.end()); 30 rep(i, N){ 31 if(D[i] < A[i]){ 32 cout << -1 << endl; 33 return 0; 34 } 35 } 36 ll right = A[N-1]; 37 ll left = A[0]; 38 ll val = (right + left) / 2; 39 ll ans = 0; 40 bool ok = false; 41 while(true){ 42 vector<ll> C = B; 43 C.push_back(val); 44 sort(C.begin(), C.end()); 45 ok = true; 46 47 rep(i,N){ 48 if(C[i] < A[i]){ 49 ok = false; 50 } 51 52 } 53 if(ok){ 54 ans = val; 55 right = val; 56 val = (right + left) / 2; 57 } 58 else{ 59 left = val; 60 ll reVal = val; 61 val = (right + left) / 2; 62 if(val == reVal){ 63 if(ans > 0){ 64 cout << ans << endl; 65 return 0; 66 } 67 } 68 } 69 70 } 71 72 return 0; 73} 74
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 int N; 8 cin >> N; 9 10 vector<ll> A(N); 11 vector<ll> B(N - 1); 12 rep(i, N) cin >> A[i]; 13 rep(i, N - 1) cin >> B[i]; 14 15 sort(A.begin(), A.end()); // Aのソート 16 17 auto canSatisfy = [&](ll x) -> bool { 18 vector<ll> C = B; 19 C.push_back(x); 20 sort(C.begin(), C.end()); 21 22 rep(i, N) { 23 if (C[i] < A[i]) return false; // 条件を満たさない場合 24 } 25 return true; // 条件を満たす場合 26 }; 27 28 ll ok = 1 << 30; // 十分大きい値 29 ll ng = 0; // 最小値 30 31 // ok と ng の二分探索 32 if (!canSatisfy(ok)) { 33 cout << -1 << endl; // 最大値でも条件を満たさない場合 34 return 0; 35 } 36 37 while (ok - ng > 1) { 38 ll mid = (ok + ng) / 2; 39 if (canSatisfy(mid)) ok = mid; 40 else ng = mid; 41 } 42 43 cout << ok << endl; 44 return 0; 45} 46
2つ質問させてください。
1. 「計算量」というのは「実行時間」のことだと考えればいいでしょうか?いわゆる「ランダウの記号」の意味だと同じ計算量になりそうに見えます。
2. 少なくとも上のコードと下のコードで以下の部分の実行時間が違うことは把握されているでしょうか?
[上のコードの47-52行目]
rep(i,N){
if(C[i] < A[i]){
ok = false;
}
}
[下のコードの22-24行目]
rep(i, N) {
if (C[i] < A[i]) return false; // 条件を満たさない場合
}
ご質問ありがとうございます。
1.実行時間のことです。
2.上と下の実行時間の違いを理解していません。なぜ違いが生じるのでしょうか。
また、AtCoderで問題を解くにあたり、意識しなければならないほど大きな違いが生まれるのでしょうか。
上のコードだと、強制的にN回分のデータの比較が発生します。
下のコードだと、条件に合致しない場合には即座に処理を終了します。
このため、下のコードの方が確実に高速に動作するロジックになります。
while(true)ループの中で毎回実行される内容のため、支配的ではありませんが、ある程度処理時間に影響を与える可能性があります。
break文が入っているのと同等ということですね。
言われるまで気づきませんでした。
ご回答ありがとうございました。