题意理解
这道题目第一问是要求出,最长的非上升子序列的长度。
第二问可以用到结论:对于一个偏序集,其最少链划分数等于其最长反链的长度。此时只需要求出最长非下降子序列的长度。
可以参考这篇文章。
于是,这条题目就变成了两次DP。
对于DP,可以参考这篇文章。
这题细节有点多,对于大于小于号需要对于状态有着正确的理解才行。
代码
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static final int maxn = 100010;
static int[] a = new int[maxn];
static int[] dp = new int[maxn];
static int len = 1;
public static void main(String[] args) {
int cnt = 1;
FastScanner fs = new FastScanner();
// 获取输入
while(true) {
if(fs.hashNext()) {
a[cnt] = fs.nextInt();
cnt++;
} else {
break;
}
}
// 特判一下没有值的情况
if(cnt == 1) {
System.out.println(0);
System.out.println(0);
return;
}
dp[1] = a[1];
for(int i = 2; i < cnt; i++) {
if(a[i] <= dp[len]) {
len++;
dp[len] = a[i];
} else {
int j = upperBound(dp, 1, len + 1, a[i]);
dp[j] = a[i];
}
}
System.out.println(len);
for(int i = 0; i < cnt + 5; i++) {
dp[i] = 0;
}
len = 1;
dp[1] = a[1];
for(int i = 2; i < cnt; i++) {
if(a[i] > dp[len]) {
len++;
dp[len] = a[i];
} else {
int j = lowerBound(dp, 1, len + 1, a[i]);
dp[j] = a[i];
}
}
System.out.println(len);
}
public static int upperBound(int[] a, int l, int r, int key) {
while (l < r) {
int m = l + (r - l) / 2;
if(a[m] >= key) {
l = m + 1;
} else {
r = m;
}
}
return l;
}
public static int lowerBound(int[] a, int l, int r, int key) {
while (l < r) {
int m = l + (r - l) / 2;
if(a[m] >= key) {
r = m;
} else {
l = m + 1;
}
}
return l;
}
public static class FastScanner {
private BufferedReader br;
private StringTokenizer st;
public FastScanner() {
br = new BufferedReader(new InputStreamReader(System.in));
}
public FastScanner(String s) {
try {
br = new BufferedReader(new FileReader(new File(s)));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public boolean hashNext() {
while(st == null) {
try {
st = new StringTokenizer(br.readLine());
} catch (Exception e) {
e.printStackTrace();
}
}
return st.hasMoreTokens();
}
public String nextToken() {
while(st == null || !st.hasMoreElements()) {
try {
st = new StringTokenizer(br.readLine());
} catch (Exception e) {
}
}
return st.nextToken();
}
public int nextInt() {
return Integer.valueOf(nextToken());
}
}
}