ynoi做题日记
关键点在于用bitset对可行性dp进行优化。
对三角函数有一定了解就很简单。
本题关键点在于将区间问题,转化为每个点对于区间的贡献(以达成可以通过莫队解决的需求),结合容斥,我们可以得到,出现了\(k\)次的权值\(x\)对于一个区间的贡献为\((2^{t}-2^{t-k})*x\)
但是我们还无法直接进行莫队,因为在我们移动左右端点的过程中,区间长度发生了变化,所以我们需要用链表存储当前区间内出现的数即相应出现的次数。
直接用链表维护所有值可以过这道题,但是常数极大,考虑优化。
我们想到根号分治,对于出现次数\(<\sqrt{n}\)的点,我们维护一个数组\(sum\),\(sum_i\)表示出现次数为\(i\)的数的权值之和,对于出现次数\(< \sqrt{n}\)的点,按上面的方法维护
但是到这里还没完,如果我们直接使用快速幂的话,就会导致我们的时间复杂度多出了一个\(log\),是我们无法接受的,所以本题要使用光速幂。如果你不会光速幂,看这个
本题的修改操作很不寻常,不再是连续的一段区间,但如果对于这种不定长的跳跃问题,应该想到根号分治,即步长越大步数越小,对于步长\(>\sqrt{n}\)的点,我们直接暴力,因为总点数是不超过\(\sqrt{n}\)的,对于步长\(<sqrt{n}\)的点,我们可以从模数的角度出发,因为这里的模数\(y\)数量是不超过\(\sqrt{n}\)的,所以我们在修改的时候统计一下对于模\(i\)余\(0∼j\)的数分别打上标记,同时使用前缀和进行优化
由逆序对,我们想到归并排序,由标题,我们想到分块
我们先从修改开始思考,这里我们需要维护的贡献有,整块间的贡献,左右散块内的贡献,左右散块间的贡献,散块与整块间的贡献。
对于一类贡献,可以直接预处理,对于二类贡献可以通过预处理块内前缀和和后缀和来统计,四类贡献,预处理一个\(cnt[i][j]\)表示前\(i\)个块中,小于等于(或大于等于)\(j\)的元素个数,查询时我们枚举散块的每个值即可,对于三类贡献,直接用归并求
于上题基本相同
移步莫莫学习笔记
本题有个弱化版[Violet] 蒲公英,先考虑弱化版,本题的关键点在于一个性质,分块之后的区间众数必然为整块的众数或者散块中的某个数,有了这个性质之后很容易写出一个时间复杂度为\(O(n\sqrt{n})\),空间复杂度也为\(O(n\sqrt{n})\)的代码。
但是这样是无法AC本题的,会MLE,我们注意到空间的瓶颈在于我们处理散块的\(cnt\)数组上,所以我们采用另一种维护方式,记录所有值为\(x\)的位置,存放到一个\(vector\)。
如何询问呢,假设我们当前询问区间\([l,r]\),我们当前处理是位于\(w\)的值为\(x\)的点,这是\(x\)这个权值第\(y\)次出现,并且当前众数出现次数为\(res\),如果\(x\)这个权值第\(y+res-1\)次出现的位置\(<r\),则将\(res++\)。
直接判断显然不可做,我们把它转化为两个条件,一是区间最大值-区间最小值=\(r-l\),二是区间无重复。
第一个条件不用说,第二个条件我们可以记录每个点上次出现的位置\(x\),求一个区间最大值,如果区间最大值比\(l\)小,那么区间必然无重复。
另外这题还有个严格加强版算术天才⑨与等差数列,只要多维护一个差分数组\(gcd\)即可
这题是个平平无奇的区间最大值,但是\(n\)奇大无比,所以无论是空间还是时间都需要做到\(O(n)\),我们预处理一个st表维护整块,预处理前缀和后缀来维护散块即可。
首先一眼看出根号分治,然后对于出现次数小于\(\sqrt(n)\)用哈希表,否则用bitset
线段树对左右端点是否选分别维护,以及该情况下是否取左右端点。
读入顺序写错调了2h,服了
三个区间问题乍一看无从下手,但是从莫队的角度去想的,如果我们能用某种可以快速合并且空间占用小的数据类型来记录答案的,三个区间和一个区间就没有本质区别了,由此我们想到了bitset,但是很遗憾的是,这题似乎不能看做一个可行性问题。
真不能吗?这里的转换有点难想,我们对于每个数字单独去想,我们希望的是不同区间里的相同数字能占用同一个位置,但是我们又希望同一个区间里的相同数字不能占用同一个数字。那么答案就呼之欲出了,我们用先预处理出有多少个数比当前数小(其实在离散化的时候别去重就行了),可以理解为我们给每个数划定了一个区间,然后每次我们加入一个数的时候,同步更新它当前出现的次数s,并且在bitset中更新我们给该数划定区间第s个位置即可。
当然,到这里还没完,你会发现我们没法开这么大的bitset,这里又涉及到一个trick,我们直接将询问分批处理,你也可以理解成是多组数据问题。

浙公网安备 33010602011771号