Cod sursa(job #2985810)

Utilizator highonrocketfuelOverweight Raccoon highonrocketfuel Data 27 februarie 2023 09:31:40
Problema Subsir crescator maximal Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.74 kb
#include <algorithm>
#include <fstream>
#include <iostream>

#define r inFile
#define w outFile

const int NMAX = 1e5;

int n;
int a[1 + NMAX];

int prev[1 + NMAX];
int dp[1 + NMAX];

// if i remember correctly this should work (famous last words)
int best_val_with_len[1 + NMAX];

void printPath(int i, std::ostream &str) {
  if (i == 0) {
    return;
  }

  printPath(prev[i], str);
  str << a[i] << ' ';
}

// returns the index not than the value
int binary_search(int start, int end, int value) {
  // std::printf("Seeking %d (a = %d)\n", value, a[value]);
  int ans = 0;
  while (start <= end) {
    int midpoint = (start + end) >> 1;
    // std::printf("Midpoint = %d (best_val = %d)\n", midpoint,
    //             best_val_with_len[midpoint]);

    if (a[best_val_with_len[midpoint]] < a[value]) {
      // std::printf("Value is less than target, saving ans to %d\n", midpoint);
      ans = midpoint;
      start = midpoint + 1;
    } else {
      // std::printf("Value is no less than target, not saving shit\n");
      end = midpoint - 1;
    }
  }

  return ans;
}

int main() {
  std::ifstream inFile("scmax.in");
  std::ofstream outFile("scmax.out");

  r >> n;

  for (int i = 1; i <= n; ++i) {
    r >> a[i];
  }

  // dp[i] - longest str. increasing subarray ending at position i

  dp[1] = 1;
  prev[1] = 0;
  a[0] = -1;
  best_val_with_len[0] = 0; // anything can be added after an empty seq
  best_val_with_len[1] = 1;
  int best_val_length = 1; // actual length of best_val_with_len, so zeros don't
                           // fuck up my binary search
  for (int i = 2; i <= n; ++i) {
    // std::printf("Currently at i = %d, array = [ ", i);
    // for (int j = 0; j <= best_val_length; ++j) {
    //   std::printf("%d(%d) ", best_val_with_len[j], a[best_val_with_len[j]]);
    // }
    // std::printf("]\n");

    // find the max length L, so that best_val_with_len[L] < a[i]
    // also a[best_val_with_len[]] SHOULD be increasing

    int j = binary_search(0, best_val_length, i);
    // std::printf("Found j = %d\n", j);

    prev[i] = best_val_with_len[j];
    dp[i] = dp[best_val_with_len[j]] + 1;

    // update the best_val array with the current value
    if (a[i] < a[best_val_with_len[dp[i]]]) {
      best_val_with_len[dp[i]] = i;
    }

    // if we found a new max, save it
    if (dp[i] > best_val_length) {
      best_val_length = dp[i];
      best_val_with_len[dp[i]] = i;
    }
  }

  // for (int i = 1; i <= n; ++i) {
  //   std::printf("%d ", dp[i]);
  // }
  // std::printf("\n");

  int ans = 0;
  for (int i = 1; i <= n; ++i) {
    if (dp[i] > dp[ans]) {
      ans = i;
    }
  }

  w << dp[ans] << '\n';

  printPath(ans, w);

  return 0;
}