Problem p02585 (C++) — buggy submission, verdict: Runtime Error

/*~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=
*$* WRITER:kakitamasziru/OxOmisosiru *$*
~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=*/
#ifdef LOCAL_JUDGE
#define _GLIBCXX_DEBUG
#endif
#include <algorithm> // min, max, swap, sort, reverse, lower_bound, upper_bound
#include <cstdint>   // int64_t, int*_t
#include <iomanip>
#include <iostream> // cout, endl, cin
#include <limits>   //setprecision
#include <string>   // string, to_string, stoi
#include <tuple>    // tuple, make_tuple
#include <utility>  // pair, make_pair
#include <vector>   // vector
// #include <cstdio> // printf
#include <map>   // map
#include <queue> // queue, priority_queue
#include <set>   // set
// #include <unordered_set> //unordered_set
#include <bitset> // bitset
#include <cmath>  //abs,,,
#include <deque>  // deque
#include <math.h> //pow,,,
#include <stack>  // stack
#define endl "\\n";
using namespace std;

const long long INF = 4000000000000000001;
const int inf = 1001001001;
const int MOD = 1000000007;
typedef pair<long long, long long> P;

// Solve N^M. This, mod_pow use Iterative Square Method.
long long mod_pow(long long N, long long M) {
  if (M == 0)
    return 1;
  long long res = mod_pow((N * N) % MOD, M / 2);
  // When end-of-a-lin bit is 1, times simple N.
  if (M & 1)
    res = (res * N) % MOD;
  return res %= MOD;
}
long long gcd(long long a, long long b) {
  if (b == 0)
    return a;
  else
    return gcd(b, a % b);
}
long long lcm(long long a, long long b) { return a / gcd(a, b) * b; }

vector<pair<int, long long>> Edge(5005);
// howMove:始点全探索　どのように動くか
vector<vector<int>> howMove(5005);
// howScore:始点全探索　スコアがどうなるか
vector<vector<long long>> howScore(5005);

int main() {
  ios::sync_with_stdio(false);
  std::cin.tie(nullptr);

  int N;
  cin >> N;
  long long K;
  cin >> K;
  vector<int> to(N), coin(N);
  for (int i = 0; i < N; i++)
    cin >> to.at(i), to.at(i)--;
  for (int i = 0; i < N; i++)
    cin >> coin.at(i);
  for (int i = 0; i < N; i++) {
    Edge.at(i).first = to.at(i);
    Edge.at(i).second = coin.at(to.at(i));
  }

  // 開始地点を全探索してどんなループをたどるか
  for (int i = 0; i < N; i++) {
    vector<bool> seen(N);
    seen.at(i) = true;
    int now = to.at(i);
    long long score = 0;
    bool loop = false;
    while (true) {
      if (loop)
        break;
      if (seen.at(now))
        loop = true;
      seen.at(now) = true;
      howMove.at(i).push_back(now);
      score += coin.at(now);
      now = to.at(now);
      howScore.at(i).push_back(score);
    }
  }

  // 始点を全探索　がんばる
  long long ans = -INF;
  for (int i = 0; i < N; i++) {
    long long score = 0;
    int needToLoopCount = howMove.at(i).size();
    if (needToLoopCount >= K) {
      score = howScore.at(i).at(0);
      // K回の操作ではループが発生しない時、一巡目のスコアの最小値を取ればよい
      for (int j = 1; j < K; j++) {
        score = max(score, howScore.at(i).at(j));
      }
      ans = max(score, ans);
    }
    if (needToLoopCount < K) {
      // K回以内の操作でループに突入できる時、がんばる（はい？）
      // ループで増えないならループせずに一巡目で止めた方が良い
      if (howScore.at(i).back() <= 0) {
        score = howScore.at(i).at(0);
        for (int j = 1; j < howScore.at(i).size(); j++) {
          score = max(score, howScore.at(i).at(j));
        }
        ans = max(score, ans);
      } else {
        // ループで増えるならループを回した方が良い
        long long canloop = K / needToLoopCount;
        long long amari = K % needToLoopCount;
        // ループは回しすぎない！！！！！！！ canloop-1回で済ませる
        score += (canloop - 1) * howScore.at(i).back();
        // ループ1回と余りを愚直にする
        long long extraPlus = 0;
        long long nowPlus = 0;
        for (int j = 0; j < amari + needToLoopCount; j++) {
          nowPlus += (coin.at(howMove.at(i).at(j % needToLoopCount)));
          extraPlus = max(extraPlus, nowPlus);
        }
        score += extraPlus;
        ans = max(ans, score);
      }
    }
  }
  cout << ans << endl;
}

Error: 0

Fixed submission:

/*~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=
*$* WRITER:kakitamasziru/OxOmisosiru *$*
~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=*/
#ifdef LOCAL_JUDGE
#define _GLIBCXX_DEBUG
#endif
#include <algorithm> // min, max, swap, sort, reverse, lower_bound, upper_bound
#include <cstdint>   // int64_t, int*_t
#include <iomanip>
#include <iostream> // cout, endl, cin
#include <limits>   //setprecision
#include <string>   // string, to_string, stoi
#include <tuple>    // tuple, make_tuple
#include <utility>  // pair, make_pair
#include <vector>   // vector
// #include <cstdio> // printf
#include <map>   // map
#include <queue> // queue, priority_queue
#include <set>   // set
// #include <unordered_set> //unordered_set
#include <bitset> // bitset
#include <cmath>  //abs,,,
#include <deque>  // deque
#include <math.h> //pow,,,
#include <stack>  // stack
#define endl "\\n";
using namespace std;

const long long INF = 4000000000000000001;
const int inf = 1001001001;
const int MOD = 1000000007;
typedef pair<long long, long long> P;

// Solve N^M. This, mod_pow use Iterative Square Method.
long long mod_pow(long long N, long long M) {
  if (M == 0)
    return 1;
  long long res = mod_pow((N * N) % MOD, M / 2);
  // 最下位ビット(*N)が1の時は単独でNをかける
  if (M & 1)
    res = (res * N) % MOD;

  return res %= MOD;
}

long long gcd(long long a, long long b) {
  if (b == 0)
    return a;
  else
    return gcd(b, a % b);
}
long long lcm(long long a, long long b) { return a / gcd(a, b) * b; }

vector<pair<int, long long>> Edge(5005);

int main() {
  ios::sync_with_stdio(false);
  std::cin.tie(nullptr);

  int N;
  long long K;
  cin >> N >> K;
  vector<int> next(N);
  for (int i = 0; i < N; i++) {
    cin >> next.at(i);
    next.at(i)--;
  }
  vector<long long> score(N);
  for (int i = 0; i < N; i++) {
    cin >> score.at(i);
  }
  for (int i = 0; i < N; i++) {
    int to = next.at(i);
    long long sc = score.at(to);
    Edge.at(i).first = to;
    Edge.at(i).second = sc;
  }

  vector<long long> maxiScore(N, -INF);
  for (int i = 0; i < N; i++) {
    long long count = 1;
    long long maxiScore_i = -INF;
    vector<bool> seen(N);
    vector<long long> rui;
    rui.push_back(0);
    vector<long long> ruiMax;
    ruiMax.push_back(-INF);
    int now = i;
    bool loopornot = false;
    while (true) {

      seen.at(now) = true;
      int next = Edge.at(now).first;
      long long getscore = Edge.at(now).second;
      rui.push_back(rui.at(count - 1) + getscore);
      ruiMax.push_back(max(ruiMax.at(count - 1), rui.at(count)));
      if (seen.at(next)) {
        loopornot = true;
        break;
      }
      if (count == K) {
        // count--;
        break;
      }
      count++;
      now = next;
    }
    if (rui.at(count) > 0) {
      if (loopornot) {
        long long loop = K / count;
        long long Loop = K / count - 1;
        maxiScore_i = loop * rui.at(count);
        long long maybeMaxi2 = Loop * rui.at(count), more2 = K - Loop * count;
        long long more = K - loop * count;
        long long moreMax = 0, moreMax2 = 0;
        for (int j = 0; j < more2; j++) {
          moreMax2 = max(moreMax2, rui.at(j + 1));
        }
        maybeMaxi2 += moreMax2;
        for (int j = 0; j < more; j++) {
          moreMax = max(moreMax, rui.at(j + 1));
        }
        long long maybeMaxi = ruiMax.back();
        maxiScore_i += moreMax;
        maxiScore_i = max({maxiScore_i, maybeMaxi, maybeMaxi2});
      } else {
        maxiScore_i = ruiMax.back();
      }
    } else {
      if (loopornot) {
        long long loop = K / count;
        maxiScore_i = loop * rui.at(count);
        long long more = K - loop * count;
        long long moreMax = 0;
        for (int j = 0; j < more; j++) {
          moreMax = max(moreMax, rui.at(j + 1));
        }
        long long maybeMaxi = ruiMax.back();
        maxiScore_i += moreMax;
        maxiScore_i = max(maxiScore_i, maybeMaxi);
      } else {
        maxiScore_i = ruiMax.back();
      }
    }
    maxiScore.at(i) = maxiScore_i;
  }

  long long OUTPUT = -INF;
  // for(long long V : maxiScore) cout << V << endl;
  for (long long V : maxiScore)
    OUTPUT = max(OUTPUT, V);
  cout << OUTPUT << endl;
}