华为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+1
			parent_[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=e

tasks.sort(key=lambda x:(x[1],x[0]))
parent=list(range(max_e+2))

def find(x:int)->int:
	root=x
	while parent[root]!=root:
		root=parent[root]
	while parent[x]!=x:
		p=parent[x]; parent[x]=root; x=p
	return root

_done=0
for s,e in tasks:
	day=find(s)
	if day<=e:
		parent[day]=find(day+1)
		_done+=1

print(_done,end="")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ai因思坦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值