ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P7447 [Ynoi2007] rgxsxrs 题解

2022-08-01 11:32:06  阅读:140  来源: 互联网

标签:log 分块 题解 复杂度 Ynoi2007 链表 值域 rgxsxrs 线段


特别劝退的一道题目。

调了整整两天,码长 4.39kb -> 6.89kb

这道毒瘤题不仅卡时间,还卡空间。

题意

给定一个长为 \(n\) 的序列 \(a\),需要实现 \(m\) 次操作:

1 l r x:表示将区间 \([l,r]\) 中所有 \(>x\) 的元素减去 \(x\)。

2 l r:表示询问区间 \([l,r]\) 的和,最小值,最大值。

思路

一看到题以为是类似第二分块的做法,后来发现了强制在线和巨大的值域范围。

首先看到要维护的值有和,最小值,最大值,可以想到可能可以用线段树维护。

但又由于这是 \(\text{Ynoi}\),所以还需要套一个分块。

考虑对于值域进行分块。

由于值域有 \(10^9\) 的大小,所以普通的根号分块显然不行,可以考虑 \(\log\) 分块。

具体来说,就是将值域分成 \(\log\) 个块,第 \(i\) 个块所存放的是 \(a^i-a^{i+1}\) 的值域。

在每个块内维护一颗动态开点线段树,以在原序列中的位置为下标,如果在减的过程中,值域不在这一块,则暴力删除修改。

如何进行修改。

  • 若此时节点最大值小于等于 \(x\),则可直接退出。

  • 若此时节点最小值大于 \(x\),同样可以直接打上标记然后退出。

  • 若都没有,则继续递归不断处理。

查询则可以直接像普通线段树一样查询。

考虑修改块的复杂度,每一个数最多改变 \(\log\) 次块,故复杂度为 \(O(n \log w \log n)\),其中 \(w\) 为值域。

在考虑查询和修改的复杂度,由于就是普通的在线段树上的操作,所以复杂度同样为 \(O(n \log w \log n)\)。

这样的代码,你会获得 \(53pts\) 的好成绩。

你会发现你 \(\text{MLE}\) 掉了。

算一下空间,你就发现这道题居然也卡了空间。

考虑一个以时间换空间优化线段树空间的方法。

可以发现,线段树最下面几层的节点,占据了大量空间,考虑把底层换为分块来解决。

每次遍历到叶子节点的块时,直接暴力操作。

这样虽然时间效率变低了,但空间就被大量优化。

底层分块的实现可以尝试使用链表来维护,算一种常数小也比较好写的方法。

  1. 插入一个数时,直接接在此时的末尾的后面,复杂度 \(O(1)\)。

  2. 删除一个数,同样是链表的基础操作,复杂度 \(O(1)\)。

  3. 在做减法操作,下穿标记等操作时,只能遍历整个链表,复杂度 \(O(len)\),其中 \(len\) 为链表长度。

这个玩意总得复杂度可能不怎么好算,但感觉也不会太慢。

实测,底层块长开 \(100\),\(\log\) 分块开 \(14\) 进制,跑得比较快。

Code

标签:log,分块,题解,复杂度,Ynoi2007,链表,值域,rgxsxrs,线段
来源: https://www.cnblogs.com/mfeitveer/p/16539548.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有