首页 > 其他分享 >Triangle: The Data Structure(优秀の二维 ST 表)

Triangle: The Data Structure(优秀の二维 ST 表)

时间:2024-08-25 18:27:11浏览次数:12  
标签:Triangle int st frac 三角形 ST Data 我们

link.
这种 RMQ 对像我这样萌新来说只有两种比较直观的方案:

  1. 线段树
  2. ST 表

首先考虑线段树,如果是朴素的一维线段树,那么我们只能一行一行地扫,显然相比暴力优化了一些,但不多,最终还是会愉快地 T 掉(亲测)。
然后我不会超冷门的数据结构二维线段树。
所以蒟蒻只能用好写的 ST 表了,只不过也是二维的。

开写!

首先观察一下样例(事实证明有时样例是很重要的),我们发现它并没有按照题目描述读入:

   1  
  2 3 
 4 5 6
7 8 9 0

实际上它是这么读的:

1
2 3
4 5 6
7 8 9 0

也就是说我们读入的和需要查询的其实都是一个等腰直角三角形。
那么我们按照惯用套路,设 \(st_{i,j,k}\) 表示以第 \(i\) 行第 \(j\) 列的点为上顶点的直角边长是 \(2^k\) 的三角形区域内的最大值,那么它的两条直角边分别是 \(i\rightarrow i+2^k-1\) 和 \(j\rightarrow j+2^k-1\)。
然后我们像平常一样再次发现了问题:
我们的普通二维 ST 表是针对矩形(准确来说应该是正方形)而言的,我们发现一个 \(st_{i,j,k}\) 的矩形可以恰好由 \(st_{i,j,k-1}\)、\(st_{i,j+2^{k-1},k-1}\)、\(st_{i+2^{k-1},j,k-1}\) 和 \(st_{i+2^{k-1},j+2^{k-1},k-1}\) 四个已经算过的矩形构成,如图所示:

但是对于三角形来说我们可就没有这么幸运了:

我们发现一个 \(st_{i,j,k}\) 的等腰直角三角形无法由 \(st_{i,j,k-1}\)、\(st_{i+2^{k-1},j,k-1}\) 和 \(st_{i+2^{k-1},j+2^{k-1},k-1}\) 三个三角形契合起来,我们会留下中间一个灰色区域。
怎么办?我们尝试在原来的大三角形的底边正中间处再放置一个边长是 \(2^{k-1}\) 的三角形,这个三角形可以用 \(st_{i+2^{k-1},j+2^{k-2},k-1}\) 来表示(我标红的那一段正好是大三角形的底边长的 \(\frac{1}{4}\)):

但是好像还没有覆盖全?那就再在原三角形的另一条直角边和斜边的正中间再加一个吧!

此时我们就覆盖完全了,另外添加的那两个三角形可以用 \(st_{i+2^{k-2},j,k-1}\) 和 \(st_{i+2^{k-2},j+2^{k-2},k-1}\) 表示。
不难证明 \(\forall \frac{n}{2}\le m<n\),一个边长是 \(n\) 的三角形都可以由不多于 \(6\) 个边长是 \(m\) 的三角形完全覆盖。
由于我们解决的是可重复贡献问题,我们直接用这 \(6\) 个三角形更新大的即可。
为了避免没用的循环,我们只需要枚举到满足 \(2^k\le h\) 的最大的 \(k\) 即可(\(h\) 是我们需要查询的边长)。
注意到需要查询的 \(h\) 是一定的,也就是 \(k\) 是一定的,因为你不这么干会 MLE,所以可以把 st 数组滚动起来,最后枚举 \(k\) 的维只开到 \(2\) 即可。
于是就有了预处理部分的代码:

read (n) ,read (h) ;
f (i ,1 ,n ,1) {
    f (j ,1 ,i ,1) {
        read (st[i][j][0]) ;
    }
}
for (int i = 0 ; ;i ++) {
    if (h >= (1 << i)) k = i ;
    else break ;
} // 找到最大的 k
f (t ,1 ,k ,1) {
    int u = t & 1 ,v = u ^ 1 ; // 分奇偶性讨论即可,注意奇数的上一个状态是偶数,反之亦然,那么 u 就是当前状态,v 是上一个状态
    f (i ,1 ,n - (1 << t) + 1 ,1) {
        f (j ,1 ,i ,1) {
            st[i][j][u] = max (st[i][j][v] ,max (st[i + (1 << t - 1)][j][v] ,st[i + (1 << t - 1)][j + (1 << t - 1)][v])) ;
            if (t > 1) { // <= 1 的时候没必要
                st[i][j][u] = max (st[i][j][u] ,max (st[i + (1 << t - 1)][j + (1 << t - 2)][v] ,max (st[i + (1 << t - 2)][j][v] ,st[i + (1 << t - 2)][j + (1 << t - 2)][v]))) ;
            }
        }
    } 
}

接下来就是查询部分,思路基本一致,但是注意到 \(h\) 不一定是 \(2\) 的正整数次幂,所以添加的三个三角形不再能直接表示为上面那样了,我们注意到我们添加的三个三角形都是在边的正中间的,那么我们来推导一下到底该怎么表示,以大三角形下面那个为例:

我们可以知道 \(1\) 号边减 \(2\) 号边等于 \(\frac{h-2^k}{2}\),由于我们作的是中垂线,那么 \(1\) 号减 \(2\) 号就等于 \(3\) 号减 \(4\) 号,得 \(5\) 号的长是 \(\frac{h-2^k}{2}\),也就是说我们添加的(红色的那个)三角形的顶点距离侧面的那条直角边的距离是 \(\frac{h-2^k}{2}\),那么它可以用 \(st_{i+h-1-2^k+1,j+\frac{h-2^k}{2},k-1}\) 来表示(\((i,j)\) 是大三角形的上顶点)。
同理可以得到其他两个三角形的表示。
那么我们的查询:

inline int query (int x ,int y) {
    int _ = x + h - 1 ,__ = y + h - 1 ;
    int u = k & 1 ; // 求出 k 对应的第三维下标
    int ans = max (st[x][y][u] ,max (st[_ - (1 << k) + 1][y][u] ,st[_ - (1 << k) + 1][__ - (1 << k) + 1][u])) ; // 正常的 ST 表查询操作
    if (k <= 1) return ans ; // 没必要在加那三个三角形了
    int t = (h - (1 << k)) >> 1 ;
    ans = max (ans ,max (st[_ - (1 << k) + 1][y + t][u] ,max (st[x + t][y][u] ,st[x + t][y + t][u]))) ; // 就是上面我说的那个
    return ans ;
} 

标签:Triangle,int,st,frac,三角形,ST,Data,我们
From: https://www.cnblogs.com/Tomoyuki-Mizuyama/p/18379276

相关文章

  • Exploring the Nexus of Large Language Models and Legal Systems: A Short Survey
    本文是LLM系列文章,针对《ExploringtheNexusofLargeLanguageModelsandLegalSystems:AShortSurvey》的翻译。探索大型语言模型与法律制度的联系:一个简短的调查摘要1引言2大型语言模型在法律任务中的应用3不同国家和地区的微调大型语言模型4大型语言......
  • Python3.11二进制AI项目程序打包为苹果Mac App(DMG)-应用程序pyinstaller制作流程(App
    众所周知,苹果MacOs系统虽然贵为Unix内核系统,但由于系统不支持N卡,所以如果想在本地跑AI项目,还需要对相关的AI模块进行定制化操作,本次我们演示一下如何将基于Python3.11的AI项目程序打包为MacOS可以直接运行的DMG安装包,可以苹果系统中一键运行AI项目。MacOs本地部署AI项目首先确......
  • pytest+allure生成测试报告
    1.安装allure-pytest插件allure生成报告是先生成结果再生成报告需要运行的代码:pytesttest_demo2.py--alluredir…report/tmp......
  • Java中stream的详细用法
    原文地址:https://www.cnblogs.com/Ao0216/p/15319553.html一、概述Stream是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用StreamAPI对集合数据进行操作,就类似于使用SQL执行的数据库查询。也可以使......
  • EPIC Institute of Technology Round August 2024 (Div. 1 + Div. 2)
    Preface两个礼拜前打的比赛拖到现在才写博客,我只能说也是个神人了这场其实D2很快就想到做法了,但自己把自己给否了,后面不管了实现了一发交上去发现过了然后这天由于12点左右室友就关灯睡觉了,我写完D2后看了眼E没仔细想就睡觉去了,后面发现E其实很trivialA.Distance......
  • STC89C52单片机外部中断与定时器中断寄存器配置分析
    参考:STC89C52手册摘自手册:中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的。当中央处理器CPU正在处理某件事的时候外界发生了紧急事件请求,要求CPU暂停当前的工作,转而去处理这个紧急事件,处理完以后,再回到原来被中断的地方,继续原来的工作,这样的过程称为中断。实现这种......
  • Storage:Keeping memories in the brain(存储:把记忆保存在大脑中)
    Onceyou’veencodedinformation,younowneedtostoreit.Unfortunately,forgettingisamajorpartofhowourbrainswork.Mostofuscan’trememberwhatwehadfordinnerTuesday,threeweeksago.However,wecanallrememberourfirstkiss.一旦完成......
  • STL案例-评委打分
    #include<iostream>usingnamespacestd;#include<vector>#include<deque>#include<algorithm>classPerson{public: Person(stringname,intscore) { this->m_Name=name; this->m_Score=score; } stringm_Name; intm......
  • POLIR-Society-Organization-真实社政: 人性{黑、白、灰}: + 管理Strategy的(整体/组织
    手机实名制+虚拟卡号手机实名制防止电诈减少犯罪发生;虚拟卡号确实有正面意义与负面意义正面意义:"虚拟号"的政策本身是好的没问题的;例如,社会性的研究;即使“不法分子”使用“虚拟号”诈骗犯罪,群众的“警惕性”更高更易察觉;因为:“虚拟号段”已经“预先分类”过,筛选......
  • Java Stream:高效编程的利器与潜在陷阱
    Java8引入的StreamAPI为处理集合数据提供了一种全新的方式,使开发者能够以声明性风格进行操作。Stream流使得代码更加简洁优雅,同时也提高了并行处理的效率。然而,Stream流的使用也带来了一些潜在的缺点。本文将深入分析JavaStream流操作的优缺点。一、JavaStream流操作的优......