当前位置: 首页 > news >正文

2024 天梯赛——工业园区建设题解

思路

将点 i i i 视为固定点, 点 j j j 视为灵活点,其中 s i = 1 s_{i} = 1 si=1 s j = 0 s_{j} = 0 sj=0。维护四个队列,其中 q 0 q_{0} q0 q 1 q_{1} q1 分别维护还没有被选用的固定点 和 灵活点, Q 0 Q_{0} Q0 Q 1 Q_{1} Q1 分别维护 正在被使用的固定点 和 灵活点。此外,维护一个 rnum 表示当前位置右边(包含当前位置)正在被使用的固定点和灵活点的总数,维护 dis 表示当前的最优答案.

依次求解位置 i = 0, 1, …, n - 1 情况下的最优解,并动态更新队列和rnum,在此基础上探索四个队列的一些基本性质:
x x x 属于 q 0 ∪ q 1 q_{0} \cup q_{1} q0q1 的点 和 y y y 属于 Q 0 ∪ Q 1 Q_{0} \cup Q_{1} Q0Q1 的点

  1. Q 0 Q_{0} Q0 Q 1 Q_{1} Q1 的交集为空 且并集为当前位置的最优解.
  2. 每次更新完队列后,对于任意的 x x x,均有 x > i x > i x>i. 因为当我们扫描到位置 i i i 时,点 x = i x = i x=i 必定属于最优解,因此点 i i i 必定已被加入 Q 0 Q_{0} Q0 或者 Q 1 Q_{1} Q1.
  3. m i n { x } > m a x { y } min \{x\} > max \{y\} min{x}>max{y}. 因为当 存在 x 0 < y 0 x_{0} < y_{0} x0<y0 时,那么 i < x 0 < y 0 i < x_{0} < y_{0} i<x0<y0,将 x 0 x_{0} x0 替换 y 0 y_{0} y0会更优.

如何维护上述数据?

  1. 当扫描到 i 时,如果点 i - 1 属于上一个位置的最优解,那么 rnum -= 1 且 dis -= (2 * rnum - k).

  2. 选用 q 0 q_{0} q0 q 1 q_{1} q1 中的最左端的点 x_left,判断是否允许用来替换 Q 0 Q_{0} Q0 Q 1 Q_{1} Q1 中的最左端的点 y_left。显然,x_left >= i 且 x_left > y_left。当 x_left - i <= i - y_left时,将 x_left 替换 y_left 并更新 rnum 和 dis. 此外,当 x_left 来自 q 0 q_{0} q0 时,它允许替换 Q 0 Q_{0} Q0 Q 1 Q_{1} Q1中的点. 当 x_left 来自 q 1 q_{1} q1 Q 1 Q_{1} Q1的大小 < m 时,它允许替换 Q 0 Q_{0} Q0 Q 1 Q_{1} Q1 中的点,否则只能替换 Q 1 Q_{1} Q1中的点. 循环执行上述步骤,直到条件不能满足.

显然,每一轮替换后,确保 Q 0 Q_{0} Q0 Q 1 Q_{1} Q1 更新为最优解. 此外,当 y y y 在位置 i 被抛弃后,它不可能再成为 位置 j (j > i)的最优解.

时间复杂度: O ( n ) O(n) O(n)

Code

#include<bits/stdc++.h>
using namespace std;
using i64 = long long;void solve() {int n, m, k;std::cin>>n>>m>>k;std::string s;std::cin>>s;std::vector<i64>ans(n);std::vector<int>vis(n);std::array<std::queue<int>, 2> q, Q;for(int i = 0;i < n;i++) {if(s[i] == '1') {q[0].push(i);} else {q[1].push(i);}}m = std::min(m, (int)q[1].size());i64 dis = 0, rnum = k;for(int i = 0;i < k;i++) {if(!q[0].empty() && (!q[1].empty() && Q[1].size() < m)) {if(q[0].front() < q[1].front()) {Q[0].push(q[0].front());dis += q[0].front();vis[q[0].front()] = 1;q[0].pop();} else {Q[1].push(q[1].front());dis += q[1].front();vis[q[1].front()] = 1;q[1].pop();}} else if(!q[0].empty()) {Q[0].push(q[0].front());dis += q[0].front();vis[q[0].front()] = 1;q[0].pop();} else {assert(Q[1].size() < k);Q[1].push(q[1].front());dis += q[1].front();vis[q[1].front()] = 1;q[1].pop();}}ans[0] = dis;auto Oper = [&] (int i, int j, int p)->bool {assert(!q[i].empty());assert(!Q[j].empty());assert(q[i].front() >= p);if(q[i].front() - p > p - Q[j].front()) {return false;}assert(Q[j].front() <= p);vis[Q[j].front()] = 0;dis -= (p - Q[j].front());Q[j].pop();dis += (q[i].front() - p);vis[q[i].front()] = 1;rnum += 1;Q[i].push(q[i].front());q[i].pop();return true;};auto calc = [&](int op, int i) ->bool{bool res = false;if(op == 0 || Q[1].size() < m) {if(!Q[0].empty() && (!Q[1].empty() && m)) {int cs = (Q[0].front() < Q[1].front()?0 : 1);res = Oper(op, cs, i);} else if(!Q[0].empty()) {res = Oper(op, 0, i);} else if(!Q[1].empty()){res = Oper(op, 1, i);}} else if(m > 0){res = Oper(1, 1, i);}return res;};for(int i = 1;i < n;i++) {if(vis[i - 1] == 1) {rnum -= 1;}//  在当前点集的作用下,dis 的更新方式如下:dis -= rnum;dis += (k - rnum);bool ok = true;while((!q[0].empty() || !q[1].empty()) && ok) {ok = false;int cs = -1;if(!q[0].empty() && (!q[1].empty() && m)) {cs = (q[0].front() < q[1].front()?0 : 1);} else if(!q[0].empty()) {cs = 0;} else if(!q[1].empty() && m){cs = 1;}if(cs != -1) {ok = calc(cs, i);}}ok = true;while(!q[0].empty() && ok) {ok = false;if(!Q[0].empty() && !Q[1].empty()) {int cs = (Q[0].front() < Q[1].front()?0 : 1);ok = Oper(0, cs, i);} else if(!Q[0].empty()) {ok = Oper(0, 0, i);} else if(!Q[1].empty()){ok = Oper(0, 1, i);}}ans[i] = dis;}for(int i = 0;i < n;i++) {std::cout<<ans[i];if(i + 1 < n) {std::cout<<" ";}}
} int main(){std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int t = 1;std::cin>>t;while(t--) {solve();if(t) {std::cout<<"\n";}}return 0;
}

http://www.mrgr.cn/news/97338.html

相关文章:

  • C++ 内存访问模式优化:从架构到实践
  • 协同控制与分布式控制 —— 理论、案例与交互式 GUI 实现
  • 进程内存分布--之理论知识
  • 从零实现本地大模型RAG部署
  • 小刚说C语言刷题——第16讲 switch语句
  • 【Linux学习笔记】初识进程概念和进程PCB
  • 构建企业级表单验证系统:可配置化验证器设计与实现
  • C语言中单向链表:创建节点与插入新节点
  • btrfs , ext4 , jfs , xfs , zfs 对比 笔记250406
  • 基于BP神经网络的杂草智能识别系统(杂草识别、Python项目)
  • pulsar中的延迟队列使用详解
  • 消息队列基础概念及选型,常见解决方案包括消息可靠性、消息有序、消息堆积、重复消费、事务消息
  • 整车CAN网络和CANoe
  • C# Winform 入门(12)之制作简单的倒计时
  • WEB安全--内网渗透--LMNTLM基础
  • 计算机系统--- BIOS(基本输入输出系统)
  • JCR一区文章,壮丽细尾鹩莺算法Superb Fairy-wren Optimization-附Matlab免费代码
  • iOS APP集成Python解释器
  • 设计模式简述(十三)适配器模式
  • 高频面试题(含笔试高频算法整理)基本总结回顾65