You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
5.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class_2022_04_1_week;
import java.util.ArrayList;
import java.util.Arrays;
// 来自通维数码
// 每个会议给定开始和结束时间
// 后面的会议如果跟前面的会议有任何冲突,完全取消冲突的、之前的会议,安排当前的
// 给定一个会议数组,返回安排的会议列表
public class Code03_ArrangeMeetingPosCancelPre {
// 比较暴力的解
// 为了对数器来验证
public static ArrayList<int[]> arrange1(int[][] meetings) {
int max = 0;
for (int[] meeting : meetings) {
max = Math.max(max, meeting[1]);
}
boolean[] occupy = new boolean[max + 1];
ArrayList<int[]> ans = new ArrayList<>();
for (int i = meetings.length - 1; i >= 0; i--) {
int[] cur = meetings[i];
boolean add = true;
for (int j = cur[0]; j < cur[1]; j++) {
if (occupy[j]) {
add = false;
break;
}
}
if (add) {
ans.add(cur);
}
for (int j = cur[0]; j < cur[1]; j++) {
occupy[j] = true;
}
}
return ans;
}
// 最优解
// 会议有N个时间复杂度O(N*logN)
public static ArrayList<int[]> arrange2(int[][] meetings) {
int n = meetings.length;
// n << 1 -> n*2
int[] rank = new int[n << 1];
for (int i = 0; i < meetings.length; i++) {
rank[i] = meetings[i][0]; // 会议开头点
rank[i + n] = meetings[i][1] - 1; // 会议的结束点
}
Arrays.sort(rank);
// n*2
SegmentTree st = new SegmentTree(n << 1);
// 哪些会议安排了放入到ans里去
ArrayList<int[]> ans = new ArrayList<>();
// 从右往左遍历,意味着,后出现的会议,先看看能不能安排
for (int i = meetings.length - 1; i >= 0; i--) {
// cur 当前会议
int[] cur = meetings[i];
// cur[0] = 17万 -> 6
int from = rank(rank, cur[0]);
// cur[1] = 90 -> 89 -> 2
int to = rank(rank, cur[1] - 1);
if (st.sum(from, to) == 0) {
ans.add(cur);
}
st.add(from, to, 1);
}
return ans;
}
public static int rank(int[] rank, int num) {
int l = 0;
int r = rank.length - 1;
int m = 0;
int ans = 0;
while (l <= r) {
m = (l + r) / 2;
if (rank[m] >= num) {
ans = m;
r = m - 1;
} else {
l = m + 1;
}
}
return ans + 1;
}
public static class SegmentTree {
private int n;
private int[] sum;
private int[] lazy;
public SegmentTree(int size) {
n = size + 1;
sum = new int[n << 2];
lazy = new int[n << 2];
n--;
}
private void pushUp(int rt) {
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
private void pushDown(int rt, int ln, int rn) {
if (lazy[rt] != 0) {
lazy[rt << 1] += lazy[rt];
sum[rt << 1] += lazy[rt] * ln;
lazy[rt << 1 | 1] += lazy[rt];
sum[rt << 1 | 1] += lazy[rt] * rn;
lazy[rt] = 0;
}
}
public void add(int L, int R, int C) {
add(L, R, C, 1, n, 1);
}
private void add(int L, int R, int C, int l, int r, int rt) {
if (L <= l && r <= R) {
sum[rt] += C * (r - l + 1);
lazy[rt] += C;
return;
}
int mid = (l + r) >> 1;
pushDown(rt, mid - l + 1, r - mid);
if (L <= mid) {
add(L, R, C, l, mid, rt << 1);
}
if (R > mid) {
add(L, R, C, mid + 1, r, rt << 1 | 1);
}
pushUp(rt);
}
public int sum(int L, int R) {
return query(L, R, 1, n, 1);
}
private int query(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
return sum[rt];
}
int mid = (l + r) >> 1;
pushDown(rt, mid - l + 1, r - mid);
int ans = 0;
if (L <= mid) {
ans += query(L, R, l, mid, rt << 1);
}
if (R > mid) {
ans += query(L, R, mid + 1, r, rt << 1 | 1);
}
return ans;
}
}
// 为了测试
public static int[][] randomMeeting(int len, int time) {
int[][] meetings = new int[len][2];
for (int i = 0; i < len; i++) {
int a = (int) (Math.random() * (time + 1));
int b = (int) (Math.random() * (time + 1));
if (a == b) {
b++;
}
meetings[i][0] = Math.min(a, b);
meetings[i][1] = Math.max(a, b);
}
return meetings;
}
// 为了测试
public static int[][] copyMeetings(int[][] meetings) {
int len = meetings.length;
int[][] ans = new int[len][2];
for (int i = 0; i < len; i++) {
ans[i][0] = meetings[i][0];
ans[i][1] = meetings[i][1];
}
return ans;
}
// 为了测试
public static boolean equal(ArrayList<int[]> arr1, ArrayList<int[]> arr2) {
if (arr1.size() != arr2.size()) {
return false;
}
for (int i = 0; i < arr1.size(); i++) {
int[] a = arr1.get(i);
int[] b = arr2.get(i);
if (a[0] != b[0] || a[1] != b[1]) {
return false;
}
}
return true;
}
public static void main(String[] args) {
int n = 100;
int t = 5000;
int testTime = 20000;
System.out.println("测试开始");
for (int i = 0; i < testTime; i++) {
int len = (int) (Math.random() * n) + 1;
int[][] meetings1 = randomMeeting(len, t);
int[][] meetings2 = copyMeetings(meetings1);
ArrayList<int[]> ans1 = arrange1(meetings1);
ArrayList<int[]> ans2 = arrange2(meetings2);
if (!equal(ans1, ans2)) {
System.out.println("出错了!");
System.out.println(ans1.size());
System.out.println(ans2.size());
System.out.println("====");
}
}
System.out.println("测试结束");
}
}