2.5
2.5
[P1020 NOIP 1999 提高组] 导弹拦截 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
-
本题两个问,第一个问如下
-
step1 第一眼看到就觉得是一道线性dp的板子题,最长上升子序列。第一反应就是\(O(N^2)\)来解决,显然是会T的。转而思考优化,选用二分进行优化,时间复杂度降到\(O(NlogN)\),就可以过了
-
step2 但是重头戏并不是第一问,第一问很常规,虽然二分边界要好好搞一下容易出点意想不到的问题)。第二问我们要用到
Dilworth定理, 简单说就是一个偏序集中的最少降序个数等于该偏序集最长的上升序列(绝对上升)。那么问题已经结束了,就是求出最长上升序列就是等价于第二问所求 -
偏序集,哈斯图与Dilworth定理 - 洛谷专栏 (luogu.com.cn)想看严谨证明的可以看这里
import java.io.*;
import java.util.*;
public class Main implements Runnable {
static Scanner cin = new Scanner(System.in);
static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
static final int N = (int) (1e5 + 10);
static int[] arr = new int[N];
static int[] target = new int[N];
static int[] dp = new int[N];// dp[i]为以arr[i]为结尾的最长非递增序列
static int len = 0;
public static void main(String[] args) {
new Thread(null, new Main(), "", 1 << 29).start();
}
// public static int nextInt() throws IOException {
//
// }
@Override
public void run() {
while (cin.hasNext()) {
int x = cin.nextInt();
arr[++len] = x;
}
int l = 1;target[1] = arr[1];
for (int i = 2; i <= len; i++) {
if (target[l] >= arr[i]) {
target[++l] = arr[i];
continue;
}
int left = 1; int right = l;
while(left <= right) {
int mid = (left + right) / 2;
if (target[mid] < arr[i]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
target[left] = arr[i];
}
cout.println(l);
Arrays.fill(target, 0);
l = 1;target[1] = arr[1];
for (int i = 2; i <= len; i++) {
if (target[l] < arr[i]) {
target[++l] = arr[i];
continue;
}
int left = 1; int right = l;
while(left <= right) {
int mid = (left + right) / 2;
if (target[mid] < arr[i]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
target[left] = arr[i];
}
cout.println(l);
cout.flush();
}
}
[P2285 HNOI2004] 打鼹鼠 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- 简单的线性dp
- 设置dp数组\(dp[i]表示第i个鼹鼠出现时被抓住的鼹鼠个数\), 只要一个点小于另一个点的曼哈顿距离,那么我们就\(dp[i] = max(dp[j] + 1 , dp[i])\)
- ok,问题解决
import java.io.*;
import java.util.*;
public class Main implements Runnable {
static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
static int n, m;
static final int N = (int) (1e4 + 10);
static Mouse[] mice = new Mouse[N];
static int[] dp = new int[N];// 在打第几个鼹鼠时已经打到的鼹鼠数
public static void main(String[] args) {
new Thread(null, new Main(), "", 1 << 29).start();
}
public static int nextInt() throws IOException {
cin.nextToken();
return (int) cin.nval;
}
@Override
public void run() {
try {
n = nextInt();m = nextInt();
for(int i = 1; i <= m; i++) mice[i] = new Mouse();
for (int i = 1; i <= m; i++) {
int t, x_, y_;
t = nextInt();x_ = nextInt();y_ = nextInt();
mice[i].time = t; mice[i].x = x_; mice[i].y = y_;
}
Arrays.fill(dp, 1);
for (int i = 2; i <= m; i++) {
for(int j = 1; j < i; j++) {
if (mice[i].time - mice[j].time >=
Math.abs(mice[i].x - mice[j].x) + Math.abs(mice[i].y - mice[j].y)) {
dp[i] = Math.max(dp[j] + 1, dp[i]);
}
}
}
int ans = 0;
for(int i = 1; i <= m; i++) {
ans = Math.max(dp[i], ans);
}
cout.println(ans);
cout.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
static class Mouse {
public int time;
public int x;
public int y;
}
}
浙公网安备 33010602011771号