Pagini recente » Cod sursa (job #1486918) | Cod sursa (job #2076621) | Cod sursa (job #2222614) | Cod sursa (job #126546) | Cod sursa (job #2229968)
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
InputStream inputStream = new FileInputStream("scmax.in");
OutputStream outputStream = new FileOutputStream("scmax.out");
try (InputReader inputReader = new InputReader(inputStream);
PrintWriter printWriter = new PrintWriter(outputStream)) {
int N = inputReader.nextInt();
int[] values = new int[N + 1];
for (int i = 1; i <= N; i++) {
values[i] = inputReader.nextInt();
}
List<Integer> longestIncreasingSubSeq = Solver.solve(N, values);
printWriter.println(longestIncreasingSubSeq.size());
for (Integer entry : longestIncreasingSubSeq) {
printWriter.print(entry + " ");
}
}
}
static class Solver {
public static List<Integer> solve(int N, int[] values) {
NormalizedArray normalizedArray = new NormalizedArray(values);
int totalUniqueElems = normalizedArray.getTotalUniqueElems();
int[] longestSubseqEndingInPos = new int[N + 1];
BinaryIndexedTree binaryIndexedTree = new BinaryIndexedTree(totalUniqueElems);
int longestIncreasingSubseqSize = 0;
for (int pos = 1; pos <= N; pos++) {
int normalizedPos = normalizedArray.getNormalizedValue(pos);
int currBestValue = binaryIndexedTree.getMaxFromOneToPos(normalizedPos - 1) + 1;
longestSubseqEndingInPos[pos] = currBestValue;
binaryIndexedTree.setPos(normalizedPos, currBestValue);
longestIncreasingSubseqSize = Math.max(longestIncreasingSubseqSize, currBestValue);
}
List<Integer> solution = new ArrayList<>(N);
for (int pos = N; pos >= 1; pos--) {
if (longestSubseqEndingInPos[pos] == longestIncreasingSubseqSize) {
solution.add(values[pos]);
longestIncreasingSubseqSize--;
}
}
Collections.reverse(solution);
return solution;
}
private static class BinaryIndexedTree {
private int N;
private int[] maxValues;
public BinaryIndexedTree(int N) {
this.N = N;
this.maxValues = new int[N + 1];
Arrays.fill(maxValues, 0);
}
int leastSignificantBit(int no) {
return no & -no;
}
public void setPos(int pos, int value) {
for ( ; pos <= N; pos += leastSignificantBit(pos)) {
maxValues[pos] = Math.max(maxValues[pos], value);
}
}
public int getMaxFromOneToPos(int pos) {
int bestResult = 0;
for ( ; pos > 0 ; pos -= leastSignificantBit(pos)) {
bestResult = Math.max(bestResult, maxValues[pos]);
}
return bestResult;
}
}
private static class NormalizedArray {
int[] originalValues;
int[] sortedUniqueValues;
int uniqueElemsCount;
public NormalizedArray(int[] originalValues) {
this.originalValues = originalValues;
sortedUniqueValues = Arrays.copyOfRange(originalValues, 0, originalValues.length);
Arrays.sort(sortedUniqueValues);
uniqueElemsCount = 1;
for (int pos = 2; pos < sortedUniqueValues.length; pos++) {
if (sortedUniqueValues[pos] > sortedUniqueValues[pos - 1]) {
sortedUniqueValues[++uniqueElemsCount] = sortedUniqueValues[pos];
}
}
}
public int getTotalUniqueElems() {
return uniqueElemsCount;
}
public int getNormalizedValue(int pos) {
return Arrays.binarySearch(sortedUniqueValues, 1, uniqueElemsCount + 1, originalValues[pos]);
}
}
}
static class InputReader implements AutoCloseable {
private BufferedReader bufferedReader;
private StringTokenizer stringTokenizer;
public InputReader(InputStream inputStream) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
stringTokenizer = null;
}
private String nextToken() {
if (stringTokenizer == null || !stringTokenizer.hasMoreTokens()) {
try {
stringTokenizer = new StringTokenizer(bufferedReader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return stringTokenizer.nextToken();
}
public int nextInt() {
return Integer.parseInt(nextToken());
}
@Override
public void close() throws Exception {
bufferedReader.close();
}
}
}