1 条题解
-
0
「DDL分配」题解(基于代码分析)
题意简化
个人分 个DDL,第 个人提出方案,需要超过 的人同意(按比例?实际是人数),否则被踢掉。
目标:求前 个人时,最后一个人能分到多少DDL,否则输出 。
核心思想:贪心 + 优先队列
1. 投票条件
设当前有 个人,第 个人需要超过 的同意票。
假设他需要 票同意,则必须满足:
从代码看,实际是 的人数?
代码中:
x = max(0ll, x)和d = len - x,其中x来自输入的 减1。2. 关键变量
len:当前还"活着"的人数sum:当前已分配的DDL总数lazy:延迟标记,表示已踢掉的人的统一补偿X:这次可以复活的人数- 优先队列
q:存储(分配数 - lazy, 人数)
3. 算法流程
对每个人 :
第一步:检查合法性
如果 ,当前人必死,输出 。
第二步:踢人计算
计算需要踢掉的人数
d = len - x,其中x = v_i - 1(需要同意的票数)。用优先队列踢人:总是踢掉当前分配最少的人(DDL拿得少的人更容易被踢)。
第三步:分配决策
如果踢完人后
len == x(刚好剩下需要的人数):- 检查剩余DDL是否足够:
sum + len*(lazy+1) <= k - 如果够:计算当前人能拿到的DDL =
k - sum - len*(lazy+1) - 更新状态:
lazy++(给所有已踢掉的人补偿1个DDL) - 将之前踢掉的人复活(
X个人),加入队列 - 当前人加入队列
如果不够或条件不满足:当前人必死,输出 。
关键点
1. 贪心策略
- 总是踢掉分配最少的人(最小化损失)
- 给被踢的人统一补偿(
lazy) - 可能的话复活之前踢掉的人
2. 数据结构
- 优先队列维护(分配数,人数)对
lazy延迟标记,避免频繁更新
3. 合法性检查
- 如果 ,不可能有足够同意票
- 如果剩余DDL不够,当前人无法分配
样例解释
输入:
5 100 1 1 2 2 3过程:
- :需要0票同意,所有人(1人)活,最后1人拿100
- :需要0票,所有人(2人)活,最后1人拿100
- :需要1票,踢掉1个拿最少的人,最后1人拿99
- :需要1票,情况类似,最后1人拿99
- :需要2票,踢掉1人,最后1人拿98
输出:100 100 99 99 98
代码特点
- 使用
pair<int,int>存储(值,人数),减少队列操作 lazy标记优化- 快速IO(
ios::sync_with_stdio(false)) - 注意
long long()
复杂度
- 每个 :优先队列操作
- 总复杂度:,可过
- 1
信息
- ID
- 6029
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 1
- 已通过
- 1
- 上传者