LGR 218 some sols

news/2025/3/26 14:15:18/文章来源:https://www.cnblogs.com/SFlyer/p/18789909

T1

Sub 1

可以暴力枚举每一个 \(y\),暴力 __builtin_popcountll(y) 求出二进制中为 \(1\) 的个数。

Sub 3

对于 \(x=2^k-1\)\(x\) 二进制中 \(1\) 的个数为恰好 \(k\),那么答案为 \(0\)

正解

约定:令 \(bit(x,d)\)\(x\) 二进制中从小到大第 \(d\) 位。\(bit(x,d)\) 取值为 \(0\) 或者 \(1\)

观察到:如果对于 \(x,y\) 满足对于 \(60\sim i+1\)\(bit(x,i)=bit(y,i)\)(即一个前缀相等),并且 \(bit(x,i)<bit(y,i)\),那么即使 \(x\) 取到最大,仍有 \(x<y\)

那么我们枚举答案 \(y\)\(x\) 满足 \(60\sim i+1\)\(bit(x,i)=bit(y,i)\),而 \(bit(x,i)\neq bit(y,i)\)。因为我们给定了 \(x\),因此知道了 \(bit(x,i)\)\(bit(x,i)\) 有两种情况:

  • \(bit(x,i)=0\)。那么 \(bit(y,i)=1\),根据观察,\(x<y\)。设剩下 \(cnt\)\(1\) 要放在第 \(0\sim i-1\) 位(为什么不是 \(i\)?因为我们确定 \(y\) 的第 \(i\) 位放置了 \(1\) 了)。因为 \(x<y\),所以我们要最小化 \(|x-y|=y-x\),即要使 \(y\) 尽量小。那么贪心得将 \(1\) 放在 \(0\sim cnt-1\) 位即可。
  • \(bit(x,i)=1\)。那么 \(bit(y,i)=0\),根据观察,\(y<x\)。类似的,设剩下 \(cnt\)\(1\) 要放在第 \(0\sim i-1\) 位。因为 \(x<y\),所以我们要最小化 \(|x-y|=x-y\),即要使 \(y\) 尽量大。那么贪心得将 \(1\) 放在 \(i-1\sim i-cnt\) 位即可。

因为我们枚举的是哪一位开始不同,因此要特殊判断如果 \(x=y\) 的情况。具体的,如果 __builtin_popcountll(x)=k,答案为 \(0\)

小朋友们可能记得开 long long 了,但是小朋友(讲评人)有一次提交没有开 __builtin_popcountll()。对于求 long long 类比的二进制下 \(1\) 的数目,千万不要用 __builtin_popcount()

T2

正解


@cff_0102

为了方便,设 \(p_i\) 表示当前满足 \(a_k=i\)\(k\) 的值。交换两个位置 \(i\)\(j\) 表示交换 \(a_i\)\(a_j\)(此时 \(p_{a_i},p_{a_j}\) 也会更新)。

首先考虑 \(t\le 2\) 的情况。

如果 \(t=1\),先手一定会交换第一个满足 \(a_i\ne i\) 的位置 \(i\) 和后面的位置 \(p_i\),这样可以做到字典序最小。

如果 \(t=2\),先考虑第二步后手会干什么。类似上面 \(t=1\) 时先手的策略,后手会交换此时第一个满足 \(a_i\ne n-i+1\) 的位置 \(i\) 和后面的位置 \(p_{n-i+1}\)

接着考虑先手:

  • 如果刚开始 \(a_1=n\),先手的最优策略显然是将这个数移走,这样后手只能把这个数移回来。否则,后手可能在后面找到一个比原来字典序更大的方案。这样,最终得到的答案会和刚开始的排列完全相同。
  • 如果 \(a_1\ne n\),先手不会傻到去交换位置 \(1\)\(p_n\)。因此后手的操作肯定是交换先手操作后的位置 \(1\)\(p_n\)。可以发现,在这种情况下,等价于后手先交换现在的位置 \(1\)\(p_n\),先手再按最优方式操作:
  • 如果先手的操作不涉及位置 \(1\)\(p_n\),那么这两个操作先后显然是无关的。
  • 如果先手交换了位置 \(1\)\(i\),后手交换新的位置 \(1\)\(p_n\),那么现在的情况是位置 \(1\) 变成了 \(n\),位置 \(i\) 变成了 \(a_1\),位置 \(p_n\) 变成了 \(a_i\)。可以发现这种情况和先交换位置 \(1\)\(p_n\),再交换(原来的)位置 \(p_n\)\(i\) 是等价的。
  • 先手交换位置 \(p_n\)\(i\) 的情况同理。
  • 因此在这种情况下,可以直接交换位置 \(1\)\(p_n\),剩下的问题是位置 \(2\sim n\) 里面交换两个数使得字典序最小,就变成了前面 \(k=1\) 时讨论的方法。

代码模拟,不难做到 \(\mathcal{O}(n)\)

现在考虑 \(t>2\) 的情况。

对于 \(2\nmid t\),答案和 \(t=1\) 时答案一样。因为先手先按最优完成第一步后,\(a_1\) 必然为 \(1\),这样就和前面 \(t=2,a_1=n\) 的情况是一样的:此时后手的最优策略只能是把位置 \(1\) 再移走,否则先手可能在下一步又找到一个字典序更小的方法。如果后手把位置 \(1\) 移走了,后面先手就只能选择撤销后手的操作。

对于 \(2\mid t\),类似的,和 \(t=2\) 答案一样。可以把这种情况看成先手先操作一步,接着后手变成新的“先手”,进行 \(t'=t-1\) 次操作,最终“先手”的目标是字典序最大,“后手”的目标是字典序最小。由前面同理可得,\(2\nmid t'\) 的这种情况相当于 \(t'=1\) 的情况。因此 \(2\mid t\) 也就相当于 \(t=2\) 的情况。

那么就可以把 \(t\) 的范围缩小成 \(\le 2\),再用上面的方法解决。总复杂度 \(\mathcal{O}(n)\)


花絮:两个人轮流可以交换一个字符串的两位(也可以选择啥都不做),一个人算一轮。第一个人(即先手)希望字符串字典序越小越好,第二个人希望越大越好。现在进行 \(n\) 轮,问最终得到的字符串。

没有排列的限制,可以做吗?

T3

Partical from @EasonLiang

Sub 3

枚举 \(u,v\) 然后统计答案是很难优化的,因此我们考虑对于每个三角形统计对答案的贡献。

每个剖分形成的三角形,将多边形的边分为了三组(可以画图理解)。将这三组边按顺时针方向记为 \(S, T, U\) 三个集合,那么考虑从某个集合中的边进入,再从另一集合中的边走出,穿过该三角形所造成的贡献:

  • \(S\) 中的边为入边、\(T\) 中的边为出边,穿过该三角形时进行了一次左转;
  • \(S\) 中的边为入边、\(U\) 中的边为出边,穿过该三角形时进行了一次右转;
  • \(T\) 中的边为入边、\(U\) 中的边为出边,穿过该三角形时进行了一次左转;
  • \(T\) 中的边为入边、\(S\) 中的边为出边,穿过该三角形时进行了一次右转;
  • \(U\) 中的边为入边、\(S\) 中的边为出边,穿过该三角形时进行了一次左转;
  • \(U\) 中的边为入边、\(T\) 中的边为出边,穿过该三角形时进行了一次右转。

那么我们只需对于每个三角形计算贡献即可。我们计算计算贡献要实现区间加操作,这个可以通过差分以及前缀和做到线性。

接下来我们只需考虑如何线性求出每个三角形的顶点编号。定义一个顶点 \(u\) 的出边为输入给定的所有无向边 \((u,v)\)\((u,u\bmod n+1),((u+n-1)\bmod n,u)\)

对于 Sub 3,可以 \(\mathcal{O}(n\log n)\) 暴力求出顶点编号:枚举一个顶点,顶点出边中相邻的两条可以组成三角形,然后用 map 去重即可。

正解

考虑优化求顶点编号的过程。上述方法超时的本质原因是我们会重复计算。考虑一种类似于“分治"的计算方式:

首先我们求出以 \(1, n\) 为其中两个顶点的三角形的剩下一个顶点 \(x\)。不难发现,\(x\) 是三角剖分中与 \(1\) 连边的顶点中编号第二大的点,也是与 \(n\) 连边的顶点中编号第二小的点。

接下来,我们考虑以 \(1, x\) 为其中两个顶点、以 \(x, n\) 为其中两个顶点,且顶点不为 \(1, x, n\) 三个编号的三角形。

  • 对于其中两个顶点为 \(1, x\) 的三角形,它的剩下一个顶点 \(y\) 是与 \(x\) 连边的顶点中编号第二小的顶点;
  • 对于其中两个顶点为 \(x, n\) 的三角形,它的剩下一个顶点 \(z\) 是与 \(x\) 连边的顶点中编号第二大的顶点。

然后我们可以继续递归考虑以 \(1, y\)\(y, x\)\(x, z\)\(z, n\) 为其中两个顶点的三角形。

这种遍历方式的正确性证明:

  • 编号第二大/第二小为什么是正确的:第一步显然正确;我们在一个多边形中提取出一个一条边是外围的三角形后,可以将原来的多边形分成两个更小的多边形,并且两个更小的多边形顶点除了 \(1,n,x\) 以外不会和另一个多边形有边,保证了第二步的正确性;依次归纳即可证明。
  • 这种方法是不重不漏得计算了三角形:每一次一个大多边形分成得两个小多边形没有重叠也没有遗漏,因此正确。

因为每一个三角形只会遍历一次,因此是线性的。递归的过程只需要知道与每个 \(u\) 连接的顶点中编号次大/次小的顶点,这个显然可以线性求出。

总时间复杂度 \(O(n)\)

出题人留的 bonus:如何在线性时间内求出 \(\sum_{u \neq v} v l^2_{u, v}\)\(\sum_{u \neq v} v r^2_{u, v}\)

T4

Sub 1,2,5

可以采用暴力枚举或者暴力 dp 或者每一次询问 \(\mathcal{O}(|s|)\) 遍历的方法得出答案,不再赘述。

Sub 3,4

对于 Sub 3,注意到如果 \([l,r]\)\(0,1\) 的个数都 \(\ge k\),答案一定是 \(2^k-1\)

对于 Sub 3,4,都考察 \(0,1\) 其中一个个数很少(或远少于)另外一个的情况,用户可能有一些算法,但是和正解关系不一定很大。

正解

考虑一次询问。

和 Sub 3 一样,如果 \([l,r]\)\(0,1\) 的个数均大于等于 \(k\),那么答案一定是 \(2^k-1\)

特判掉这种情况,因为保证了 \(2k\le r-l+1\),那么现在一定是一个数的个数 \(\ge k\),一个 \(<k\)。不妨设 \(0\) 的个数大于 \(k\),另一种情况是本质相同的。

结论:存在一个最优方案,使得一个子序列全是 \(0\),另一个子序列含有所有 \(1\)。设前者为第一个子序列,后者为第二个子序列。证明放到最后。

考虑有了这个结论我们怎么计算答案。

由于异或的答案就是第二个子序列对应的数值,我们需要尽量让它大。有一个显然的贪心:从高到低如果这一位能取 \(1\) 就取 \(1\),如果取了 \(1\) 以后剩下的数个数不够无法满足长度限制,就取 \(0\)。因此有了一个 \(\mathcal{O}(nq)\) 的算法。

观察:开始取 \(0\) 以后,一定是取一个 \([l,r]\) 的后缀。也就是说,第二个子序列是以一串 \(1\) 加上一段区间的后缀组成的。

这个观察为什么是对的呢?设开始取的 \(0\) 在位置 \(y\),而上一个取的 \(1\) 在位置 \(x\)\(x\) 的下一个 \(1\) 在位置 \(z\)。那么,可以知道,\(x+1\sim z-1\) 都是 \(0\),并且 \(x<y<z\)。我们想要尽量让 \(z\) 放在尽量前的位置,本质上是最小化 \(x+1\sim z-1\) 中选择的 \(0\) 的个数。这个最小化就说明 \(z\sim r\) 的位置要尽量多选。那么最优就是 \(z\sim r\) 都选(构成了一个后缀),而 \(x+1\sim z-1\) 因为都是 \(0\),选择哪些都不影响,因此可以让 \(y\) 尽量靠后,从而整体构成一个后缀。

因此我们可以二分第一次取零的位置并且判断。对 \(s\) 做前缀和,时间复杂度 \(\mathcal{O}(n+q\log n)\)。已经可以过了。

还可以继续优化:其实我们可以算出第二个子序列要取多少个 \(0\)(可以看成 \(0\) 从后往前取),而开始的 \(0\) 的位置可以预处理 \(\mathcal{O}(1)\) 计算出。时间复杂度 \(\mathcal{O}(n+q)\)

前文所说的结论的证明:若有“更优方案”,由于 \(1\) 的数量不能更多,说明更优方案的答案有一个 \(1\) 的位置在更前面。而前文所说的方案的答案是一串 \(1\) 加上这段区间的一个后缀,原本方案前面的 \(1\) 的位置不可能更前,因此更优方案和原本答案的区别在于后面部分 \(1\) 的位置更靠前。然而原本方案后面部分是一段后缀,其中的数的位置无法继续往前提,因此这样的“更优方案”不存在,上面的策略得到的答案即为最优方案。

这个题目不卡 \(\mathcal{O}(n+q\log n)\) 的做法。

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

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

相关文章

Gitee DevOps 实践指南:本土团队效率提升的新范式

在数字化转型的浪潮中,Gitee DevOps 作为国内领先的一体化研发效能平台,通过深度融合代码托管、CI/CD、项目管理等核心功能,为企业提供了本土化的 DevOps 解决方案。一、Gitee DevOps 的核心价值定位 在数字化转型的浪潮中,Gitee DevOps 作为国内领先的一体化研发效能平台,…

那些正常的动态规划

目录前言动态规划到底是啥?线性dp最长上升子序列子集和子序列和子串的区别内容分析最大上升子序列例题1——[NOIP2004 提高组] 合唱队形分析最长公共子序列最长公共子串平面dp例题2——[NOIP2000 提高组] 方格取数分析例题3——[NOIP2008 提高组] 传纸条分析例题4——最大加权…

3月24日刷题笔记-第六章 流量特征分析-常见攻击事件 tomcat

1、在web服务器上发现的可疑活动,流量分析会显示很多请求,这表明存在恶意的扫描行为,通过分析扫描的行为后提交攻击者IP flag格式:flag{ip},如:flag 我们查看流量包,可以发现有一个外部IP在对常见端口进行SYN扫描,判断出为恶意IPflag{14.0.0.120} 2、找到攻击者IP后请通过…

如何在云效中使用 DeepSeek 等大模型实现 AI 智能评审

除了代码智能补全外,AI 代码智能评审是 DevOps 领域受开发者广泛关注的另一场景了。本文,我们将结合云效代码管理 Codeup、流水线 Flow 和 DeepSeek,分享一种企业可快速自主接入,即可实现的 AI 智能评审解决方案,希望给大家一些启发。作者:崔力强、黄博文 除了代码智能补…

T+0量化:JAVA接入Level2高频行情(附Python代码)

去年在知乎分享过一个网格策略,评论区全是"代码能跑通但实盘不敢用"的留言。当时我也一样——用第三方平台回测美滋滋,一到实盘就怂:行情延迟3秒、API调用次数受限、策略逻辑被平台规则卡脖子…直到把整套系统搬回本地,才发现自建交易系统的快感就像从合租屋搬进…

制作一个简单的带有3D打印部件的四足蜘蛛机器人

在这个项目中,我将向您展示如何使用3D打印部件制作一个简单的4腿行走蜘蛛机器人。该设计主要由上下板、臂接插件、腿和伺服支架五个部分组成。机器人的4条腿由4个手臂部分和4个腿部分组成。机器人的运动总共使用了8个业余伺服电机,4个在手臂上,4个在腿上。在电路方面,首选E…

统计学习之数据挖掘(结构数据)

统计学习之数据挖掘(结构数据):降维聚类关联度分析分类神经网络

2024 腾讯游戏安全大赛 mobile 初赛 wp

找关键结构体 https://www.cnblogs.com/revercc/p/17641855.html 找GWORLD https://bbs.kanxue.com/thread-280042.htm可以发现是 TEXT包裹的,utf-16编码,ida alt + b搜索 53 00 65 00 61 00 6D 00 6C 00 65 00 73 00 73 00 54 00 72 00即可网上翻即可找到 GWorld对应地址: 0…

制造业订单处理烦恼多,日事清 OTD 管理为您排忧解难

你是不是经常因为接单和交货时间差太大而焦头烂额?今天我们就结合制造业OTD管理,带您了解如何应用日事清进行订单交付全周期管理。日事清可以帮你设定精细的流程,从接单到发货,清晰可控地帮你解决以上烦心事。在制造业里打拼,每天都得面对各种烦心事,比如订单处理慢、生产…

如何在SSD1306上显示动态表情符号位图

解锁您的SSD1306上充满活力的视觉效果!学习毫不费力地显示动态表情符号位图,并以风格增强您的项目。 在本教程中,我们将通过使用PCBX在线模拟环境在SSD1306 OLED显示器上显示位图图像的过程。本教程将介绍设置PCBX模拟,格式化位图数据,配置显示大小和管理图像延迟。步骤1:…

redis基础数据结构——ZipList

ZipList 基于特殊写法实现的双端链表,由一系列特殊编码的连续内存块组成,可以像deque一样在双端压入/弹出,并且时间复杂度在O(1) 整体ZL结构如下zlbytes(uint32):当前zl总的byte数。 zltail(uint32):尾结点的offset,指向的是最后一个entry的起始地址。 zllen(uint16):记…