「考试」省选19

居然没出原题听奇怪。
好难啊。

T1
计算几何。
把x有交集的墙合并起来。
然后再每一个墙的端点上加入每一个\(x\)轴以上的点和这个端点的向量。
然后每个\(vector\)极角排序即可。
查询的时候对每个端点算出和当前点的向量,然后在\(vector\)中查询比这个点小的个数。
如果当前端点是左端点就+个数个,否则答案-个数个。
相当于一种差分,而会作出贡献的自然是那些被墙挡住的部分。也就是大于和起点的向量小于和终点的向量。

T2
线段树扫描线。
首先将查询的询问分成\([1,l-1]->[l,r]\)\([1,r]->[l,r]\)这两个。
然后考虑如何维护这样的前缀信息。
扫描线。
设当前扫描位置为\(l\),那么扫描线上位置\(j\)记录的信息就是\([1,l]->j\)的所有信息。
然后我们需要的扫描线是可以得到如下一个函数:

\[ans_{L,R}=\sum\limits_{i=L}^{R}f_{r,i}(r)-\sum\limits_{i=L}^{R}f_{l-1,i}(l-1) \]

这个有点麻烦了。
因为需要代入一个\(x\)而算出众多贡献。
考虑如何做。
我们将\(f\)设为一个如下的函数:

\[f(x)=ax+b \]

然后首先初始化这个函数。
先直接算出\(1->[1,n]\)的所有\(mex\),然后初始化\(a_i=mex[i],b_i=0\)
这样初始的答案就是对的了。
然后考虑修改。
维护如下一个值\(mx[x]\)表示线段树区间中\(mex[i]\)的最大值。
然后我们发现\(mex[x]\)是递增的。
我们需要修改的是一段连续的区间。
\(nxt[i]\)\(a[i]\)\(i\)之后下一次出现的位置。
也就是说当前位置从\(l\)移动到\(l+1\)的时候,对于所有的\(i\in [l+1,nxt[l]-1]\),以这些位置为终点的所有\(mex\)值均要和\(a[l]\)\(min\)
因为这些部分\(a[l]\)并没有出现。
这样我们改变\(mx[x]\)的值。
同时也要改变\(a,b\)的值。
怎么做?
我们发现贡献对于后面代入的某个值是这样的。
如果某个位置将要被修改(\(mx[x]>a[l]\)
那么对于这个位置来说,\([1,l]\)的所有起点对于当前这个右端点的贡献全部都减去\(mx[x]-a[l]\),所以\(b_x-=l*(mx[x]-a[l])\)
而同时,\([l+1,i]\)也就是需要查询代入的值这一部分是不受影响的,所以\(a_x+=mx[x]-a[l]\),这样直接用标记下传即可。
然后修改掉\(mx[x]=d\)即可。
查询的时候查询区间的\(k\)和以及\(b\)和,让他们一同做出贡献。
仍然有一个问题。
就是我们暴力的修改复杂度是无法保证的。
因此我们维护这样一个值\(s[x]=0/1\),表示当前区间的所有点是否是同一个值,修改的时候如果是同一个值直接修改,否则向下递归。
然后一种颜色加入和被覆盖的复杂度都是\(logn\),那么总的复杂度仍然是:\(O(nlogn)\)

T3
后缀排序。
考虑一种等价于最小表示法的方式。
如果当前位置为\(i\),那么\(a[i]\)出现的上个位置为\(j\),那么\(j\)的贡献即为\((i-j)*w^{j-l}\),这样会得到一个\(hash\)值。
发现这种表示方法等价于最小表示法。
然后考虑后缀排序求出\(height\)数组,然后求出本质不同字串个数。
可以直接对后缀排序,然后比较的时候用二分+\(hash\)\(lcp\),如上给出了一种\(hash\)的求法
可以用主席树进行维护。
主席树每个位置代表以当前点为右端点,主席树上的位置为左端点的后缀的前缀的\(hash\)值。
然后根据上面我说的方式进行\(hash\)的更新。
可以发现相当于在给主席树的一段前缀区间加上一个等比数列,这里由于所有的等比数列公比相同,所以直接求首项和即可标记永久化来维护这一点。
然后可以求\(hash\)了,直接二分+\(hash\)求出\(lcp\),然后比较下一个字符即可。
下一个字符可以用每种颜色的\(vector\)+\(lower_bound\)来求出。
然后就可以比较了。
比较的次数为\(nlogn\)次,每次比较的复杂度是\(log^2n\),所以总的复杂度是\(O(nlog^3n)\)
会被卡常,改成\(stable\_sort\),也就是归并排序(%%%湘源大神告诉我的)就可以过了。
另外\(height\)可以直接利用\(lcp\)来求。
这样就可以直接算出本质不同字串个数了。

posted @ 2020-02-06 19:30  Lrefrain  阅读(93)  评论(1编辑  收藏  举报