题解:P11831 [省选联考 2025] 追忆

news/2025/10/23 20:15:04/文章来源:https://www.cnblogs.com/Noivelist/p/19161551

\(\LARGE {P11831 [省选联考 2025] 追忆}\)

题解原出处

请阅读完彼题解再阅读此题解,此题解不对解题思路分析有帮助

仅仅提供代码上的解惑

我只是对他的代码进行了非常详细的注释处理,orz大佬


题意:

大哥图,考虑的是连通性和区间最大值维护 , bitset 闭包传递很好地解决连通性的问题
键值的交换直接进行 ; 权值的交换因为涉及 bitset 的更新 , 我们考虑记录下来 , 查询的时候再更新


\(\mathcal {Step\ 1:}\)初始化和图构建

// 读取测试用例数量
int testid, t; cin >> testid >> t; while(t--)// 清空邻接表,准备构建新图
for(int i = 1; i <= n; ++i) e[i].clear();// 构建有向图,e[u]存储u的所有出边邻居
for(int i = 1; i <= m; ++i)
{int u, v; cin >> u >> v;e[u].push_back(v); // 添加从u到v的有向边
}

\(\mathcal {Step\ 2:}\)数据初始化

// 读取每个节点的键值(用于后续查询)
for(int i = 1; i <= n; ++i) cin >> a[i];// 初始化权值系统和映射关系
// b[i]:节点i的权值
// wz1[b[i]] = i:权值b[i]对应的节点编号
// wz2[b[i]] = a[i]:权值b[i]对应的键值
for(int i = 1; i <= n; ++i) cin >> b[i], wz1[b[i]] = i, wz2[b[i]] = a[i];

\(\mathcal {Step\ 3:}\)bitset预处理

// 反图处理节点,确保依赖关系正确
for(int i = n; i >= 1; --i)
{// 清空当前节点的位集memset(bit[i], 0, sizeof(bit[i]));// 设置当前节点权值的位标记// b[i]>>6:确定在哪个64位块中// b[i]&63:确定在块中的具体位置(0-63)bit[i][b[i] >> 6] = (1llu << (b[i] & 63));// 合并所有后继节点的位集(可达性传播)for(int j : e[i]){for(int k = 0; k <= (n >> 6); ++k) bit[i][k] |= bit[j][k];}
}

\(\mathcal {Step\ 4:}\)查询处理核心逻辑

1: 交换键值

if(op == 1)
{cin >> x >> y;// 交换两个节点权值对应的键值映射swap(wz2[b[x]], wz2[b[y]]);
}

2: 交换权值

if(op == 2)
{cin >> x >> y;// 更新权值到节点的映射swap(wz1[b[x]], wz1[b[y]]);// 更新权值到键值的映射  swap(wz2[b[x]], wz2[b[y]]);// 记录交换历史,用于延迟更新xx[++tot] = b[x], yy[tot] = b[y];// 实际交换节点的权值swap(b[x], b[y]);
}

3: 查询操作(最复杂部分)

if(op == 3)
{cin >> x >> l >> r;// 延迟更新:处理所有未应用的交换操作while(pos[x] <= tot){// 检查交换涉及的权值在当前节点的位集中是否存在int a = (bit[x][xx[pos[x]] >> 6] >> (xx[pos[x]] & 63)) & 1;int b = (bit[x][yy[pos[x]] >> 6] >> (yy[pos[x]] & 63)) & 1;// 如果交换影响了当前节点的可达性,更新位集if(a != b){if(a == 0) {// 添加xx权值,移除yy权值bit[x][xx[pos[x]] >> 6] += (1llu << (xx[pos[x]] & 63));bit[x][yy[pos[x]] >> 6] -= (1llu << (yy[pos[x]] & 63));}else{// 移除xx权值,添加yy权值bit[x][xx[pos[x]] >> 6] -= (1llu << (xx[pos[x]] & 63));bit[x][yy[pos[x]] >> 6] += (1llu << (yy[pos[x]] & 63));}}++pos[x]; // 移动到下一个交换操作}// 执行实际查询bool flag = 0;// 从高位到低位遍历所有64位块for(int j = (n >> 6); j >= 0 && !flag; --j){if(bit[x][j] == 0) continue; // 跳过空块unsigned long long now = bit[x][j];// 遍历当前块中的所有设置位while(now != 0){// 计算具体的权值:块基址 + 位偏移int wz = (j << 6) + __lg(now);// 检查该权值对应的键值是否在查询范围内if(l <= wz2[wz] && wz2[wz] <= r){cout << wz << '\n'; // 输出满足条件的权值flag = 1;break;}// 移除当前处理的位,继续处理下一个now -= (1llu << __lg(now));}}if(!flag) cout << 0 << '\n'; // 无结果
}

算法核心思想

1. \(\textstyle \large 位集压缩‌:\)使用 unsigned long long 数组模拟大位集,每个元素管理64个权值
2. \(\textstyle \large‌ 延迟更新‌:\)交换操作不立即更新所有节点,而是记录历史,在查询时按需更新
3. \(\textstyle \large‌ 可达性传播‌:\)通过反向遍历确保子节点的信息正确传播到父节点
4. \(\textstyle \large‌ 高效查询‌:\)利用位运算快速检查权值存在性和范围条件


给出全部的代码

#include<bits/stdc++.h>
using namespace std;int n,m,q;
vector<int> e[100010];
int a[100010],b[100010];
unsigned long long bit[100010][(int)1e5/64+10];
int wz1[100010],wz2[100010];
int tot,xx[100010],yy[100010];
int pos[100010];int main()
{ios::sync_with_stdio(false),cin.tie(0);int testid,t; cin>>testid>>t; while(t--){cin>>n>>m>>q;for(int i=1; i<=n; ++i) e[i].clear();for(int i=1; i<=m; ++i){int u,v; cin>>u>>v;e[u].push_back(v);}for(int i=1; i<=n; ++i) cin>>a[i];for(int i=1; i<=n; ++i) cin>>b[i],wz1[b[i]]=i,wz2[b[i]]=a[i];for(int i=n; i>=1; --i){memset(bit[i],0,sizeof(bit[i]));bit[i][b[i]>>6]=(1llu<<(b[i]&63));for(int j:e[i]){for(int k=0; k<=(n>>6); ++k) bit[i][k]|=bit[j][k];}}tot=0;for(int i=1; i<=n; ++i) pos[i]=1;while(q--){int op,x,y,l,r; cin>>op;if(op==1){cin>>x>>y;swap(wz2[b[x]],wz2[b[y]]);}if(op==2){cin>>x>>y;swap(wz1[b[x]],wz1[b[y]]);swap(wz2[b[x]],wz2[b[y]]);xx[++tot]=b[x],yy[tot]=b[y];swap(b[x],b[y]);}if(op==3){cin>>x>>l>>r;while(pos[x]<=tot){int a=(bit[x][xx[pos[x]]>>6]>>(xx[pos[x]]&63)&1);int b=(bit[x][yy[pos[x]]>>6]>>(yy[pos[x]]&63)&1);if(a!=b){if(a==0){bit[x][xx[pos[x]]>>6]+=(1llu<<(xx[pos[x]]&63));bit[x][yy[pos[x]]>>6]-=(1llu<<(yy[pos[x]]&63));}else{bit[x][xx[pos[x]]>>6]-=(1llu<<(xx[pos[x]]&63));bit[x][yy[pos[x]]>>6]+=(1llu<<(yy[pos[x]]&63));}}++pos[x];}bool flag=0;for(int j=(n>>6); j>=0 && !flag; --j){if(bit[x][j]==0) continue;unsigned long long now=bit[x][j];while(now!=0){int wz=(j<<6)+__lg(now);if(l<=wz2[wz] && wz2[wz]<=r){cout<<wz<<'\n';flag=1;break;}now-=(1llu<<__lg(now));}}if(!flag) cout<<0<<'\n';}}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/944650.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025-10-23 MX-S 模拟赛 赛后总结【MX】

赛时 Record14:30 为何 T1 串串。 14:45 摸了字符串哈希。这真的是大洋里吗,为何这么水。 14:58 诶我草原来 T2 的 \(t_i\le 3\) 吗。 15:22 试图推 T2 神秘 dp 式。 16:00 被击败了。 16:09 写出来了,最后发现是忘了…

PCL1.12 解决memory.h中EIGEN处中断问题

PCL1.12 解决memory.h中EIGEN处中断问题在使用PCL1.12时,出现已在 VisionFormatWork.exe 中执行断点指令(__debugbreak () 语句或类似调用) 的提示。 __debugbreak() 是一个由编译器提供的 调试断点指令(类似汇编中…

深入解析:链表的核心思想

深入解析:链表的核心思想pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", &…

AI元人文构想:参与“自由与责任”哲学思考——岐金兰之实验

AI元人文构想:参与“自由与责任”哲学思考——岐金兰之实验 让我们以“AI元人文”构想为透镜,重新审视“自由与责任”这一古老的哲学谜题。这将不再是一场纯粹的思辨,而是一次为智能行为构建底层架构的思想实验。 基…

20251023

总结 A 预计:100,实际:60 用时:10min思路历程:居然看错题了,以为可以整个一段全部是一个字母,关键是样例刚好全部能过 正解:666 收获:最好多看几遍题和数据范围B 预计:100,实际:100 用时:30min思路历程:…

Java常用机制 - SPI机制详解

目录Java常用机制 - SPI机制详解简单介绍SPI工作流程SPI实现代码示例步骤 1:定义服务接口步骤 2:提供具体实现(由不同厂商提供)步骤 3:创建配置文件步骤 4:使用 ServiceLoader 发现并调用服务输出可能为:需要SP…

实用指南:用户研究:用户研究和数据分析的根本联系与区别

实用指南:用户研究:用户研究和数据分析的根本联系与区别2025-10-23 20:01 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important…

2025.10.23——2绿2蓝

普及+/提高 P2914 [USACO08OCT] Power Failure G 最短路,简单预处理 P9912 [COCI 2023/2024 #2] Zatopljenje T1,离线树状数组 提高+/省选- P9906 [COCI 2023/2024 #1] Kocke T2,没想到的DP P9031 [COCI 2022/2023 …

Anaconda命令大全conda

创建虚拟环境 conda create --name myenvpython37 python=3.7使用该虚拟环境 conda activate myenvpython37退出使用虚拟环境 conda deactivate

完整教程:状态管理库 Zustand 的接入流程与注意点

完整教程:状态管理库 Zustand 的接入流程与注意点pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas"…

采用opencv来识别信用卡的号码

采用opencv来识别信用卡的号码pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco"…

塔吊施工环境与附属设施监测!思通数科 AI 卫士筑牢全场景安全防线

塔吊施工安全不仅依赖核心部件与人员操作合规,周边环境与附属设施的隐患也常成为 “安全盲区”:塔吊周边地面是否存在积水、泥泞,易引发作业人员滑倒,但人工巡检易忽视此类环境细节;有限空间入口处安全标识、警示…

精读《C++20设计模式》:重新理解设计模式系列 - 详解

精读《C++20设计模式》:重新理解设计模式系列 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas&qu…

网络设备

1. 交换机(缓存接入的所有设备的ip,mac地址等) 2. 路由器(公司级,企业级)

Kafka-保证消息消费的顺序性及高可用机制 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

第二十二篇

今天是10月23号,上了算法课,体测1000米。

CSharp: Convert CSV to XLS Using Open XML SDK

using System; using System.Data; using System.IO; using System.Linq; using System.Text; using System.Globalization; using CsvHelper; using DocumentFormat.OpenXml; using DocumentFormat.OpenXml.Packaging…

实用指南:PyTorch 数据处理工具箱:从数据加载到可视化的完整指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

《程序员修炼之道:从小工到专家》阅读笔记1

2025年的今天,当AI代码助手能自动生成70%基础代码时,程序员的核心竞争力究竟是什么?《程序员修炼之道》序言以"生存指南"的定位给出震撼答案:真正的高手从不依赖工具,而是凭借责任意识、持续学习与批判…

多级多卡训练模型时有些参数没有参与loss计算和梯度更新的解决办法

在运行程序的bash命令中添加 export TORCH_DISTRIBUTED_DEBUG=DETAIL ,这样就可以在log或终端打印没有参与loss计算的权重参数了。