CSP202203-3
只用会用的STL,数组优先,结构体优先。
#include <bits/stdc++.h>
using namespace std;
/*
西西艾弗云有多个结点,每个结点都有唯一的编号。
西西艾弗云每个计算任务都有一个应用与之对应,每个应用可能
包含多个计算任务(一对多运算)
每个计算任务由一个特定的计算节点执行。
对于一个计算任务,主席那个它的计算节点一旦选定便不再更改,
在选定计算节点后,该计算节点的要求不再被考虑。
输入:
计算任务 和 要求
输出:
计算任务需要安排在哪个节点上
三种要求:
1. 计算任务在指定节点上运行
2. 计算任务必须和指定应用的计算任务在同一**可用区**上运行。
3. 计算任务不能和指定任务的计算任务在同一**计算节点**上运行。
(必须满足 or 尽量满足)
选择计算节点:
1. 过滤阶段,根据要求过滤出所有满足要求的计算节点。
如果没有满足要求的节点,且要求中有3,且为尽量满足,则
去除要求3,再过滤一边。如果还没有节点满足,则无法分配。
2. 将过滤后的计算节点排序:
2.1选择此时计算任务数量最少的计算节点
2.2选择编号最小的计算节点。
数据结构:
结构体:
计算节点
任务
*/
const int N = 1e3 + 10;
int n, m;
// 某个计算节点在哪个可用区中
int l[N];
// 某个区中有那些编号的计算节点
vector<int> st[N];
int sz[N];
//// 某个计算节点已经运行的任务应用类型
//vector<int> load[N];
int g;
struct Mission {
int f; //任务个数
int a; //应用编号
// 任务的三种要求
int rule1;
int rule2;
int rule3;
// 第三种要求的种类
int rule3_opt;
} mis[2 * N];
struct Node {
int cnt; // 节点编号
int l; // 节点对应的可用区
int sz; // 节点上分配的任务数
} node[N];
//确定某个应用在哪些任务区上运行。
vector<int> app_on_area[2 * N];
vector<int> app_on_node[2 * N];
// que 临时记录某个节点是否符合题意
int que[N];
// 对应用编号进行离散化,离散化到2e3范围内
int cnt;
unordered_map<int, int> mp;
int func(int x) {
if (mp.find(x) == mp.end()) {
mp.insert({x, cnt++});
return mp[x];
} else {
return mp[x];
}
}
bool cmp(Node a, Node b) {
if (a.sz == b.sz) {
return a.cnt < b.cnt;
} else
return a.sz < b.sz;
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
int tmp;
scanf("%d", &tmp);
node[i].cnt = i;
node[i].l = tmp;
st[tmp].push_back(i);
}
scanf("%d", &g);
for (int ct = 1; ct <= g; ct++) {
scanf("%d %d %d %d %d %d", &mis[ct].f, &mis[ct].a,
&mis[ct].rule1, &mis[ct].rule2, &mis[ct].rule3,
&mis[ct].rule3_opt);
// 对于同一批次的任务,也可能分类不同,所以
// 先考虑对每个任务分别处理。
for (int cc = 1; cc <= mis[ct].f; cc++) {
memset(que, 0, sizeof que);
// rule1处理
if (mis[ct].rule1 != 0) {
for (int j = 1; j <= n; j++) {
if (node[j].l != mis[ct].rule1) {
que[j]++;
}
}
}
// 符合条件的为0,不符合条件的为1.
//离散化处理
// rule2处理
if (mis[ct].rule2 != 0) {
// 运行 rule2 应用的节点
if (mp.find(mis[ct].rule2) != mp.end()) {
int tmp = func(mis[ct].rule2);
for (int j = 0; j < app_on_area[tmp].size(); j++) {
// 对应空闲区中的运算节点
for (int k = 0; k < st[app_on_area[tmp][j]].size(); k++) {
// 在 rule1可行的条件下,如果rule2也可行,则设置为2.
if (que[st[app_on_area[tmp][j]][k]] == 0) {
que[st[app_on_area[tmp][j]][k]] = 2;
}
}
}
}
} else {
for (int j = 1; j <= n; j++) {
if (que[j] == 0) {
que[j] = 2;
}
}
}
vector<Node> vv;
vv.clear();
int ans = 0;
for (int j = 1; j <= n; j++) {
if (que[j] == 2) {
vv.push_back(node[j]);
}
}
if (vv.size() == 0) {
printf("%d ", ans);
continue;
}
// 离散化处理
// rule3处理
if (mis[ct].rule3 != 0) {
if (mp.find(mis[ct].rule3) != mp.end()) {
int tmp = func(mis[ct].rule3);
for (int j = 0; j < app_on_node[tmp].size(); j++) {
if (que[app_on_node[tmp][j]] == 2) {
que[app_on_node[tmp][j]] = 3;
}
}
// printf("tmp: ");
// printf("%d\n", tmp);
// // 对应运行了 应用mis[ct].rule3 的所有任务区
// for (int j = 0; j < app_on_area[tmp].size(); j++) {
// // 任务区下面的所有运算节点
// for (int k = 0; k < st[app_on_area[tmp][j]].size(); k++) {
// // 对于rule1,rule2可行的运算节点,如果rule3不可行,设置为3.
// if (que[st[app_on_area[tmp][j]][k]] == 2) {
// que[st[app_on_area[tmp][j]][k]] = 3;
// }
// }
// }
}
}
// 排序, 服啦,需要对节点重构
// 把节点当作结构体
vector<Node> v;
v.clear();
for (int j = 1; j <= n; j++) {
if (que[j] == 2) {
v.push_back(node[j]);
}
}
if (v.size() == 0) {
if (mis[ct].rule3_opt == 0) {
sort(vv.begin(), vv.end(), cmp);
ans = vv[0].cnt;
printf("%d ", ans);
} else {
ans = 0;
printf("%d ", ans);
}
} else {
sort(v.begin(), v.end(), cmp);
ans = v[0].cnt;
printf("%d ", ans);
}
//cout << "pause" << endl;
// 维护处理时用到的数据结构 app_on_area
if (ans != 0) {
int indx = func(mis[ct].a);
app_on_area[indx].push_back(node[ans].l);
app_on_node[indx].push_back(node[ans].cnt);
node[ans].sz++;
//printf("%d\n", (int)app_on_area[0][0]);
}
}
printf("\n");
}
return 0;
}