Cod sursa(job #2128192)

Utilizator fylot3Bogdan Filote fylot3 Data 11 februarie 2018 15:29:48
Problema Subsir crescator maximal Scor 20
Compilator c Status done
Runda Arhiva educationala Marime 2.45 kb
#include "stdio.h"

#define MAX_N	100000

/* IO */
FILE *fin;
FILE *fout;

/* Problem Data */
int N;
int array[MAX_N];

int best[MAX_N];
int predecesor[MAX_N];
int max_index;

void read(void) {
	fin = fopen("scmax.in", "r");
	fscanf(fin, "%d", &N);

	int i;
	for (i = 0; i < N; i++) {
		fscanf(fin, "%d", &array[i]);
	}

	fclose(fin);
}

/*void write(void) {
	int subsequence[best[max_index]];
	int index = max_index, nr = 0, i;

	subsequence[nr++] = array[index];
	while (predecesor[index] >= 0) {
		subsequence[nr++] = array[predecesor[index]];
		index = predecesor[index];
	}

	fout = fopen("scmax.out", "w");
	fprintf(fout, "%d\n", best[max_index]);

	for (i = nr - 1; i >= 0; i--) {
		fprintf(fout, "%d ", subsequence[i]);
	}

	fclose(fout);
}*/

/* DP - simplu O(n^2) */
/*void solve(void) {
	int i, j, max_best, global_best = 0;

	best[0] = 1;
	predecesor[0] = -1;

	for (i = 1; i < N; i++) {
		predecesor[i] = -1;
		max_best = 0;
		for (j = i - 1; j >= 0; j--) {
			if (array[i] > array[j] && best[j] > max_best) {
				max_best = best[j];
				predecesor[i] = j;
			}
		}
		best[i] = 1 + max_best;
		if (best[i] > global_best) {
			global_best = best[i];
			max_index = i;
		}
	}
}*/

/* DP - folosind AIB - O(n*log n) */

#define zeros(x) ( (x ^ (x - 1)) & x )

int AIB[MAX_N+1];

/*int compute(int x) {
	int i, ret = 0;
	for (i = x; i > 0; i-= zeros(i))
		ret += AIB[i];
	return ret;
}*/


void add(int x, int q) {
	int i;

	for (i = x; i <= N; i += zeros(i)) {
		AIB[i] += q;
	}
}

int getMax(int x) {
	int i, ret = 0;
	for (i = x; i > 0; i -= zeros(i)) {
		if (array[x] > array[i-1] && best[i] > ret) {
			predecesor[x] = i-1;
			ret = best[i];
		}
	}

	return ret;
}

void solve2(void) {
	int i, global_best = 0;

	for (i = 0; i <= N; i++) {
		AIB[i] = 0;
		best[i] = 0;
	}

	add(1, 1);
	best[1] = 1;
	predecesor[0] = -1;

	for (i = 1; i < N; i++) {
		predecesor[i] = -1;
		best[i+1] = 1 + getMax(i);
		add(i+1, best[i+1]);

		if (best[i+1] > global_best) {
			global_best = best[i+1];
			max_index = i;
		}
	}
}

void write2(void) {
	int subsequence[best[max_index + 1]];
	int index = max_index, nr = 0, i;

	subsequence[nr++] = array[index];
	while (predecesor[index] >= 0) {
		subsequence[nr++] = array[predecesor[index]];
		index = predecesor[index];
	}

	fout = fopen("scmax.out", "w");
	fprintf(fout, "%d\n", best[max_index + 1]);

	for (i = nr - 1; i >= 0; i--) {
		fprintf(fout, "%d ", subsequence[i]);
	}

	fclose(fout);
}

int main(void) {
	
	read();
	solve2();
	write2();

	return 0;
}