[Trick] 折半报警器
[Trick] 折半报警器
以例题来举例:
这个Link里面的 T3。
很明显,对于一个类型 \(1\) 的操作,由抽屉原理,一定会有一个点会超过 \(\lfloor \frac{y}{k} \rfloor\) ,考虑将这个东西当作一个阈值,当其中的一个数变化大于 \(\lfloor \frac{y}{k} \rfloor\) 的时候,我们计算一共此时总数变化了多少,再重构一下就可以。
分析一下时间复杂度,我们发现每一次对于一个类型 \(1\) 的操作,会将总数至少减去 \(\frac{1}{k}\),综合下来重构次数为 \(\log_{\frac{k}{k-1}} y\) 。
上一下代码:
#include <bits/stdc++.h>
#define FASTIO \
ios::sync_with_stdio(false); \
cin.tie(0); \
cout.tie(0);
using namespace std;
using ll = long long;
using pii = pair<int, int>;
const int N = 2e5 + 5;
struct Task {
ll target;
int k;
int machines[5];
bool finished;
} tasks[N];
struct node {
ll tim;
int id;
int ver;
bool operator>(const node& o) const { return tim > o.tim; }
};
ll mtime[N];
int task_ver[N];
priority_queue<node, vector<node>, greater<node>> pq[N];
void update(int id, vector<int>& vec) {
if (tasks[id].finished)
return;
ll sum = 0;
for (int i = 0; i < tasks[id].k; ++i) {
sum += mtime[tasks[id].machines[i]];
}
if (sum >= tasks[id].target) {
tasks[id].finished = true;
vec.push_back(id);
} else {
ll rem = tasks[id].target - sum;
ll step = (rem + tasks[id].k - 1) / tasks[id].k;
task_ver[id]++;
for (int i = 0; i < tasks[id].k; ++i) {
int ano = tasks[id].machines[i];
pq[ano].push({ mtime[ano] + step, id, task_ver[id] });
}
}
}
int main() {
FASTIO;
freopen("mission.in", "r", stdin);
freopen("mission.out", "w", stdout);
int n, m;
cin >> n >> m;
int cnt_task = 1;
int lst = 0;
for (int i = 1; i <= m; ++i) {
int op;
cin >> op;
if (op == 1) {
ll y;
int k;
cin >> y >> k;
y ^= lst;
tasks[cnt_task].target = y;
tasks[cnt_task].k = k;
tasks[cnt_task].finished = false;
ll sum = 0;
for (int j = 0; j < k; ++j) {
int q;
cin >> q;
q ^= lst;
tasks[cnt_task].machines[j] = q;
sum += mtime[q];
}
tasks[cnt_task].target += sum;
vector<int> vec;
update(cnt_task++, vec);
} else {
int x;
ll y;
cin >> x >> y;
x ^= lst;
y ^= lst;
mtime[x] += y;
vector<int> vec;
while (!pq[x].empty() && pq[x].top().tim <= mtime[x]) {
node e = pq[x].top();
pq[x].pop();
if (tasks[e.id].finished || e.ver != task_ver[e.id])
continue;
update(e.id, vec);
}
sort(vec.begin(), vec.end());
cout << vec.size() << ' ';
for (int id : vec) cout << id << ' ';
cout << "\n";
lst = (int)vec.size();
}
}
return 0;
}

浙公网安备 33010602011771号