当前位置: 代码迷 >> 综合 >> A. Busiest Computing Nodes
  详细解决方案

A. Busiest Computing Nodes

热度:95   发布时间:2023-12-01 01:29:06.0

目录

题意:

思路: 

AC代码(有详细注释):


题意:

K个计算点(0 ~ k - 1),N个任务,假设从0 开始编号,第 i 个任务从第 i % k 个计算点开始往后找,如果有计算点空闲,该任务就交给它,否则跳过该任务。你需要找到接受任务最多的点,相同

则按升序输出。

思路: 

题目会给你每个任务的开始时间和完成耗时,用线段树维护区间中完成时的时间最小的点,只要在合法的区间内找到完成时间 <= 当前任务开始时间的点,那么当前任务就可以在改点计算。

开始时间:a , 完成耗时:b , 完成时间:a + b

计算点可接任务条件:当前时间 >= 计算点已接任务完成时间(a >= a+b)

AC代码(有详细注释):

#include<iostream>
#include<algorithm>// 左右孩
#define TR f << 1 | 1
#define TL f << 1using namespace std;
typedef pair<int, int> PII;
const int N = 5e5;bool ff;
int k, n;
int tr[N];// 维护区间完成时间最小值的点
PII ans[N];
//找完成时间最小的点 相同则为左孩
bool check(int f) { return tr[TL] <= tr[TR]; }void pushup(int f)
{if (check(f))tr[f] = tr[TL]; else tr[f] = tr[TR];
}
//                               合法区间起点和终点   开始时间和完成耗时
void modify(int f, int l, int r, int start, int end, int a, int b)
{if (ff)return; //如果改任务以被接受 直接返回 防止多个点接受同一个任务if (l == r){//如果当前时间>=完成时间&&区间合法(该叶子节点在i%k 的左边)if (a >= tr[f] && start <= l) { tr[f] = a + b; ans[l].first++; ff = true; }}else{int mid = l + r >> 1;//如果左孩右孩符合要求就搜 (优先搜左孩)if (mid >= start && a >= tr[TL])modify(TL, l, mid, start, end, a, b);if (mid < end&& a >= tr[TR])modify(TR, mid + 1, r, start, end, a, b);//pushup 维护区间最小值pushup(f);}
}bool cmp(PII a, PII b)
{if (a.first != b.first)return a.first > b.first;else return a.second < b.second;
}int main()
{cin >> k >> n;for (int i = 0; i < k; i++)ans[i].second = i;int i = 0;while (n--){int a, b, start = i++ % k;scanf("%d%d", &a, &b);modify(1, 0, k - 1, start, k - 1, a, b);if (!ff && start)modify(1, 0, k - 1, 0, start - 1, a, b);ff = false;}sort(ans, ans + k, cmp);printf("%d", ans[0].second);for (int i = 1; i < k; i++){if (ans[i].first == ans[i - 1].first)printf(" %d", ans[i].second);else break;}return 0;
}

  相关解决方案