Cod sursa(job #3364199)

Utilizator TimofeiFilipTimofei Filip Emanuel TimofeiFilip Data 31 august 2026 13:46:46
Problema Subsir crescator maximal Scor 15
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.06 kb
#include<bits/stdc++.h>
using namespace std;

const int NMAX = 1e5 + 10;

int lis[NMAX], v[NMAX], normalized_v[NMAX];
int pre[NMAX];
pair<int, int> aint[4 * NMAX];

void print_array(int n, int x[]) {
    for (int i = 1; i <= n; i++)
        printf("%d ", x[i]);
    printf("\n");
}
void reconstruct_array(int current_position) {
    int aux[NMAX];
    int n = lis[current_position];
    int i = n - 1;
    do {
        aux[i--] = v[current_position];
        current_position = pre[current_position];
    } while (current_position != -1);
    for (i = 0; i < n; i++) printf("%d ", aux[i]);
}
int normalize(int n) {
    map<int, int> w;
    for (int i = 1; i <= n; i++)
        w[v[i]] = 0;
    int cnt = 1;
    for (auto &x : w)
        x.second = cnt++;

    for (int i = 1; i <= n; i++)
        normalized_v[i] = w[v[i]];
    return cnt - 1;
}
void merge_nodes(pair<int, int> &dest, pair<int, int> &a, pair<int, int> &b) {
    if (a.first >= b.first) {
        dest = a;
        return;
    }
    dest = b;
}

void update_recursiv(int node, int left, int right, int position, int value) {
    if (left == right) {
        aint[node].first = value;
        aint[node].second = position;
        return;
    }
    int middle = (left + right) / 2;
    if (position <= middle)
        update_recursiv(2 * node, left, middle, position, value);
    else
        update_recursiv(2 * node + 1, middle + 1, right, position, value);
    merge_nodes(aint[node], aint[2 * node], aint[2 * node + 1]);
}
void update(int n, int p, int v) {
    update_recursiv(1, 1, n, p, v);
}
pair<int, int> query_recursiv(int node, int left, int right, int query_left, int query_right) {
    if (left == query_left && right == query_right) {
        return aint[node];
    }
    int middle = (left + right) / 2;
    if (query_right <= middle)
        return query_recursiv(2 * node, left, middle, query_left, query_right);
    if (query_left > middle)
        return query_recursiv(2 * node + 1, middle + 1, right, query_left, query_right);
    pair<int, int> a = query_recursiv(2 * node, left, middle, query_left, middle);
    pair<int, int> b = query_recursiv(2 * node + 1, middle + 1, right, middle + 1, query_right);
    pair<int, int> ans;
    merge_nodes(ans, a, b);
    return ans;
}
pair<int, int> query(int n, int l, int r) {
    return query_recursiv(1, 1, n, l, r);
}
int main() {
    freopen("scmax.in", "r", stdin);
    freopen("scmax.out", "w", stdout);

    int n; scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &v[i]);
    }
    int m = normalize(n);
    for (int i = 1; i <= n; i++) {
        pair<int, int> best_j;
        if (normalized_v[i] - 1 != 0)
            best_j = query(m, 1, normalized_v[i] - 1);
        else
            best_j = query(m, 1, 1);
        if (best_j.first == 0) pre[i] = -1;
        else pre[i] = best_j.second;
        lis[i] = best_j.first + 1;
        update(m, normalized_v[i], lis[i]);
    }
    int best_i = 0;
    for (int i = 1; i <= n; i++)
        if (lis[best_i] < lis[i])
            best_i = i;
    printf("%d\n", lis[best_i]);
    reconstruct_array(best_i);
    return 0;
}