Cod sursa(job #2818377)

Utilizator GrandmasterSoucup Bogdan Grandmaster Data 15 decembrie 2021 22:45:41
Problema Subsir crescator maximal Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.35 kb
#include <iostream>
#include <stdio.h>
#include <unordered_map>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>

using namespace std;

#define point pair<int32_t, int32_t>
#define mmap unordered_map<int32_t, int32_t>

unordered_map<uint64_t, int32_t> arb;

uint64_t getIndex(int32_t x, int32_t y) {
  return (uint64_t)x * 100000ULL + (uint64_t)y;
}

void add(int32_t *sets, int32_t value, int32_t pos, int32_t left, int32_t right, int32_t n) {
  if(pos < left || pos > right) {
    return ;
  }
  if(left == right && left == pos) {
    sets[pos] = value;
    arb[getIndex(left, right)] = value;
    return ;
  }
  int32_t m = (left + right) / 2;
  add(sets, value, pos, left, m, n);
  add(sets, value, pos, m + 1, right, n);
  if(left <= pos && right >= pos) {
    //sets[getIndex(left, right, n)] = max(sets[getIndex(left, m, n)], sets[getIndex(m + 1, right, n)]);
    arb[getIndex(left, right)] = max(arb[getIndex(left, m)], arb[getIndex(m + 1, right)]);
  }
}

void addIntervalTree(int32_t *sets, int32_t value, int32_t pos, int32_t n) {
  add(sets, value, pos, 0, n - 1, n);
}

int32_t getMax_t(int32_t *sets, int32_t n, int32_t left, int32_t right, int32_t iniLeft, int32_t iniRight) {
  if(left >= iniLeft && right <= iniRight) {
    //return sets[getIndex(left, right, n)];
    return arb[getIndex(left, right)];
  }
  if((left < iniLeft && right < iniLeft) || (right > iniRight && left > iniRight)) {
    return 0;
  }
  int32_t m = (left + right) / 2;
  int32_t leftMax = getMax_t(sets, n, left, m, iniLeft, iniRight);
  int32_t rightMax = getMax_t(sets, n, m + 1, right, iniLeft, iniRight);
  return max(rightMax, leftMax);
}

int32_t getMax(int32_t *sets, int32_t n, int32_t left, int32_t right) {
  if(left >= right) {
    return sets[left];
  }
  return getMax_t(sets, n, 0, n - 1, left, right);
}

void rebuild(FILE *fr, int32_t *trueSets, int32_t *buffer, int32_t index, mmap &indexes) {
  int32_t currentValue = buffer[indexes[trueSets[index]]];
  vector<int32_t> art;
  art.push_back(trueSets[index]);
  while(currentValue != 1 && index >= 0) {
    int32_t newIndex = indexes[trueSets[index]];
    if(buffer[newIndex] + 1 == currentValue) {
      art.push_back(trueSets[index]);
      currentValue--;
    }
    index--;
  }
  for(int32_t i = art.size() - 1; i >= 0; i--) {
    fprintf(fr, "%d ", art[i]);
  }
}

int main() {
  FILE *fd = fopen("scmax.in", "r+");
  FILE *fr = fopen("scmax.out", "w+");

  int32_t n, *buffer = (int32_t *)malloc(sizeof(int32_t) * 440004);
  memset(buffer, 0, sizeof(int32_t) * 440004);
  int32_t *sets = (int32_t *)malloc(sizeof(int32_t) * 100004), *trueSets = (int32_t *)malloc(sizeof(int32_t) * 100004);
  fscanf(fd, "%d", &n);
  mmap indexes;
  for(int32_t i = 0; i < n; i++) {
    fscanf(fd, "%d", &sets[i]);
    trueSets[i] = sets[i];
  }
  sort(sets, sets + n);
  for(int32_t i = 0; i < n; i++) {
    indexes[sets[i]] = i;
  }
  int32_t totalMax = 1, finalIndex = 0;
  for(int32_t i = 0; i < n; i++) {
    int32_t newIndex = indexes[trueSets[i]];
    int32_t maxElement = getMax(buffer, n, 0, newIndex - 1) + 1;
    if(totalMax < maxElement) {
      finalIndex = i;
      totalMax = maxElement;
    }
    addIntervalTree(buffer, maxElement, newIndex, n);
  }
  fprintf(fr, "%d\n", totalMax);
  rebuild(fr, trueSets, buffer, finalIndex, indexes);
}