public void fillTimeFirstSolved() {
   standings.forEach(
       teamInfo -> {
         ArrayList<RunInfo>[] runs = teamInfo.getRuns();
         for (int i = 0; i < runs.length; i++) {
           for (RunInfo run : runs[i]) {
             if (run.isAccepted()) {
               timeFirstSolved[i] = Math.min(timeFirstSolved[i], run.getTime());
             }
           }
         }
       });
 }
  public void makeRuns() {
    ArrayList<RunInfo> runs = new ArrayList<>();
    for (TeamInfo team : standings) {
      for (List<RunInfo> innerRuns : team.getRuns()) {
        runs.addAll(innerRuns);
      }
    }
    this.runs = runs.toArray(new PCMSRunInfo[0]);
    Arrays.sort(this.runs);

    firstSolvedRuns = new PCMSRunInfo[problemNumber];
    for (RunInfo run : this.runs) {
      if (firstSolvedRuns[run.getProblemNumber()] == null
          && run.isAccepted()
          && run.getTime() <= FREEZE_TIME) {
        firstSolvedRuns[run.getProblemNumber()] = run;
      }
    }
  }
  public TeamInfo[] getPossibleStandings(boolean optimistic) {
    TeamInfo[] original = getStandings();

    PCMSTeamInfo[] standings = new PCMSTeamInfo[original.length];
    for (int i = 0; i < original.length; i++) {
      standings[i] = (PCMSTeamInfo) original[i].copy();
      List<RunInfo>[] runs = original[i].getRuns();
      for (int j = 0; j < problemNumber; j++) {
        int runIndex = 0;
        for (RunInfo run : runs[j]) {
          PCMSRunInfo clonedRun = new PCMSRunInfo(run);

          if (clonedRun.getResult().length() == 0) {
            clonedRun.judged = true;
            String expectedResult = optimistic ? "AC" : "WA";
            clonedRun.result = runIndex == runs[j].size() - 1 ? expectedResult : "WA";
            clonedRun.reallyUnknown = true;
          }
          standings[i].addRun(clonedRun, j);
          runIndex++;
        }
      }
    }
    for (PCMSTeamInfo team : standings) {
      team.solved = 0;
      team.penalty = 0;
      team.lastAccepted = 0;
      List<RunInfo>[] runs = team.getRuns();
      for (int j = 0; j < problemNumber; j++) {
        int wrong = 0;
        for (RunInfo run : runs[j]) {
          if ("AC".equals(run.getResult())) {
            team.solved++;
            int time = (int) (run.getTime() / 60 / 1000);
            team.penalty += wrong * 20 + time;
            team.lastAccepted = Math.max(team.lastAccepted, run.getTime());
            break;
          } else if (run.getResult().length() > 0 && !"CE".equals(run.getResult())) {
            wrong++;
          }
        }
      }
    }

    Arrays.sort(standings, TeamInfo.comparator);

    for (int i = 0; i < standings.length; i++) {
      if (i > 0 && TeamInfo.comparator.compare(standings[i - 1], standings[i]) == 0) {
        standings[i].rank = standings[i - 1].rank;
      } else {
        standings[i].rank = i + 1;
      }
    }
    return standings;
  }