P7448 [Ynoi2007] rdiq

区间本质不同逆序对,要求线性空间。

O ( n n × n ) \mathcal O(n \sqrt n \times \sqrt n) O(nn ×n ) 应该谁都会做,而且谁都知道不能过。

回顾 P5047,考虑莫队二次离线。

f ( l , r ) f(l,r) f(l,r) [ l , r ] [l,r] [l,r] > a r >a_r >ar 的数的种类数。

则区间转移从 [ l , r − 1 ] [l,r-1] [l,r1] 变成 [ l , r ] [l,r] [l,r],令 r ′ r' r a r a_r ar 上一次出现的位置,则贡献为 f ( l , r ) − f ( l , r ′ ) f(l,r)-f(l,r') f(l,r)f(l,r),其他方向和一连段转移同理。

考虑到种类数难以维护,尝试通过扫描线转换为总数,问题转化为查询区间内比一个数小的数的个数,需要 O ( n ) \mathcal O(n) O(n) 次单点修改, O ( n n ) \mathcal O(n \sqrt n) O(nn ) 次矩阵和查询,第一维是下标,第二维是值域,此时点的横坐标和纵坐标一一对应,即横坐标和纵坐标两两不同。

我们需要一个针对上述问题的 O ( n ) − O ( 1 ) \mathcal O(\sqrt n)-\mathcal O(1) O(n )O(1) 数据结构。

引入二维分块,即对 n × n n\times n n×n 的矩阵进行适当地分块,使得块数 O ( n ) \mathcal O(\sqrt n) O(n ) 且支持 O ( n ) − O ( 1 ) \mathcal O(\sqrt n)-\mathcal O(1) O(n )O(1) O ( 1 ) − O ( n ) \mathcal O(1)-\mathcal O(\sqrt n) O(1)O(n )

首先用将整个矩形用 n 0.75 × n 0.75 n^{0.75}\times n^{0.75} n0.75×n0.75 来分块(如图红色部分),这样总块数为 O ( n 0.25 × n 0.25 = n ) \mathcal O(n^{0.25}\times n^{0.25}=\sqrt n) O(n0.25×n0.25=n ) 的,整块复杂度保证。

考虑分剩余块,使得较小块复杂度保证,不证:

  • n 0.25 × n 0.25 n^{0.25}\times n^{0.25} n0.25×n0.25 n 0.75 × n 0.5 n^{0.75}\times n^{0.5} n0.75×n0.5 大小的块,蓝色部分。
  • n 0.25 × n 0.25 n^{0.25}\times n^{0.25} n0.25×n0.25 n 0.5 × n 0.76 n^{0.5}\times n^{0.76} n0.5×n0.76 大小的块,绿色部分。
  • n 0.25 × n 0.25 n^{0.25}\times n^{0.25} n0.25×n0.25 n 0.5 × n 0.5 n^{0.5}\times n^{0.5} n0.5×n0.5 大小的块,橙色部分。

如图,例: 155 155 155

[外链图片转存中…(img-LKhH8CdI-1655162111518)]

最后考虑灰色块复杂度,由于询问横坐标和纵坐标两两不同,而灰色块宽度不超过 O ( n ) \mathcal O(\sqrt n) O(n ),涉及的询问只有 O ( n ) \mathcal O(\sqrt n) O(n ) 种,故散块修改 O ( n ) \mathcal O(\sqrt n) O(n ),查询 O ( 1 ) \mathcal O(1) O(1),复杂度保证。

时间复杂度为 O ( n n ) \mathcal O(n\sqrt n) O(nn ),空间复杂度为 O ( n ) \mathcal O(n) O(n)

CODE

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TokenType.SYMBOL_LEFT_PAREN) { match(TokenType.SYMBOL_LEFT_PAREN); expression(); match(TokenType.SYMBOL_RIGHT_PAREN); } else { throw new Exception("Syntax error"); } } private void match(TokenType type) throws Exception { if (tokenList.get(index).getType() == type) { index++; } else { throw new Exception("Syntax error"); } } private int getVariableAddress(String identifier) throws Exception { if (!symbolTable.containsKey(identifier)) { 这是一道程序设计竞赛题目,需要设计算法来解决。题目描述为: 有一个大小为 $ throw new Exception("Undefined variable"); } return symbolTable.get(identifier); } } ``` 在语义分析程序n\times m$ 的网格图,每个格子中有一个整数。定义一个点 $(i,j)$ 的权中,我们首先定义了四个成员变量:词法单元列表、当前处理的词法单元下标、符号表和四元式列表。其中符号表用于存储变量名和对应的内存地址,值为 $a_{i,j}$ 与其上下左右四个点权值的和的乘积,即 $a四元式列表用于存储生成的四元式。 然后,我们定义了一系列方法来进行语义分_{i,j}\times (a_{i-1,j}+a_{i+1,j}+a_{i,j-1}析和生成四元式。这些方法分别对应PL/0语言的不同语法结构,例如程序+a_{i,j+1})$。现在你需要找到一个点 $(i,j)$,使得其权值最、块、语句、表达式、项和因子。在处理每个语法结构时,我们先判断当前大,输出这个最大权值。 需要用到搜索算法或动态规划算法来解决这个问题,具体实现可以参考题目解析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值