华为OD最新机试真题-可以处理的最大任务数-OD统一考试(C卷)
题目描述
在某个项目中有多个任务(用tasks数组表示)需要您进行处理,其中tasks0=[si,ei],你可以在si<= day<= ei中的任意一天处理该任务,请返回你可以处理的最大任务数
输入描述
第一行为任务数量n,1<=n<= 100000。后面n行表示各个任务的开始时间和终止时间,使用si,ei表示,1<= si<= ei<= 100000
输出描述
输出为一个整数,表示可以处理的最大任务数。
示例
输入
3
1 1
1 2
1 3
输出
3
说明
解题思路
1、 将任务按结束日 e 升序(若相同按开始日升序)排序。
2、扫描任务;对每个任务 [s,e],用一个“并查集 nextDay”找到不早于 s 的最早可用日期 day:find(s)。若 day<=e,则在这一天处理该任务,并把 day 合并到 day+1(表示下次从 day+1 往后找)。
3、并查集表示:parent[d]=d 意味着 d 仍可用;占用后令 parent[d]=find(d+1)。路径压缩可使查询近似 O(1)。
复杂度:排序 O(n log n);并查集近似 O(n)。总复杂度 O(n log n)。
c++解法:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;struct Task { int s, e; };static int parent_[100000 + 5 + 1]; // +1 预留哨兵int find_next(int x) {// 迭代版路径压缩,避免深递归int r = x;while (parent_[r] != r) r = parent_[r];while (parent_[x] != x) { int p = parent_[x]; parent_[x] = r; x = p; }return r;
}int main() {ios::sync_with_stdio(false);cin.tie(nullptr);int n; if (!(cin >> n)) return 0;vector<Task> a(n);int maxE = 0;for (int i = 0; i < n; i++) {cin >> a[i].s >> a[i].e;if (a[i].e > maxE) maxE = a[i].e;}sort(a.begin(), a.end(), [](const Task& x, const Task& y) {if (x.e != y.e) return x.e < y.e;return x.s < y.s;});// 初始化并查集:parent_[d] = d 表示 d 这一天还未被占用for (int d = 0; d <= maxE + 1; d++) parent_[d] = d;int done = 0;for (const auto& t : a) {int day = find_next(t.s); // 从 s 起找第一个可用日if (day <= t.e) {// 占用 day,并把它的 next 指向 day+1parent_[day] = find_next(day + 1);++done;}}cout << done;return 0;
}
java解法:
import java.io.*;
import java.util.*;// 最大可完成任务数:每任务区间 [s,e] 内任选一天完成,且每天最多做 1 个任务
// 解法:结束日升序贪心 + 并查集(Next Available Day)
public class Main {static int[] parent;static int find(int x){int r = x;while(parent[r] != r) r = parent[r];while(parent[x] != x){ int p = parent[x]; parent[x] = r; x = p; }return r;}public static void main(String[] args) throws Exception {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));int n = Integer.parseInt(br.readLine().trim());int[][] a = new int[n][2];int maxE = 0;for(int i=0;i<n;i++){String[] parts = br.readLine().trim().split("\\s+");int s = Integer.parseInt(parts[0]);int e = Integer.parseInt(parts[1]);a[i][0] = s; a[i][1] = e;if(e > maxE) maxE = e;}Arrays.sort(a, (x,y) -> x[1] != y[1] ? Integer.compare(x[1], y[1]) : Integer.compare(x[0], y[0]));parent = new int[maxE + 2];for(int d=0; d<=maxE+1; d++) parent[d] = d;int done = 0;for(int[] t : a){int day = find(t[0]);if(day <= t[1]){parent[day] = find(day + 1);done++;}}System.out.print(done);}
}
python解法:
import sys
# 最大可完成任务数:每任务 [s,e] 内任选一天处理一次,且每天最多 1 个
# 贪心:按结束日排序 + 并查集(Next Available Day)
data=sys.stdin.read().strip().split()
if not data:sys.exit(0)
it=iter(data)
n=int(next(it))
tasks=[]
max_e=0
for _ in range(n):s=int(next(it)); e=int(next(it))tasks.append((s,e))if e>max_e: max_e=etasks.sort(key=lambda x:(x[1],x[0]))
parent=list(range(max_e+2))def find(x:int)->int:root=xwhile parent[root]!=root:root=parent[root]while parent[x]!=x:p=parent[x]; parent[x]=root; x=preturn root_done=0
for s,e in tasks:day=find(s)if day<=e:parent[day]=find(day+1)_done+=1print(_done,end="")