THUWC前集训Day6

THUWC前集训Day6

T1 string

关键就是求串(S)的所有本质不同子串的本质不同子串数量和,记为1型串和2型串。

首先你最好做过区间本质不同子串数量,和那个是一样的套路。

就是先建SAM,然后依次加入右端点(r)并考虑所有以(r)为右端点的子串。对SAM的影响就是改变了一条到根的链上的所有点的endpos,钦定所有2型串在当前最晚的出现位置产生贡献。从下往上爬这条链,如果某个点之前已经被访问过,那么其表示的所有子串的贡献都撤销(在线段树上区间-1即可),并标记为被(r)访问。最后将([1,r])区间+1.此时线段树上([l,r])的区间和即为([l,r])的本质不同子串数量,爬的过程可以用LCT维护,可以做到每个(r)复杂度均摊(mathcal O(log n))

现在要对所有1型串求这个事情。我的做法是让每个1型串在最早的出现位置产生贡献,先假设都不同,答案加上(sum_{i=1}^rSum(i,r),Sum(i,r))为线段树上([i,r])区间和 。爬的时候如果某个点之前已经被访问过,那么将其贡献(设其表示了([minl,maxl])这些串,那么贡献为(sum_{i=minl}^{maxl}Sum(i,r)) )撤销。令线段树维护区间加,询问区间后缀和的和即可。

复杂度(mathcal O(nlog n)). (注意不是2个log,LCT的虚实边切换是均摊(O(1))的)

My code

T2 Cubelia

关键就是询问一个区间的所有子区间的最小值之和。

离线可以莫队或者排序之后线段树,不必展开。

做法是求出最小值位置(pos),那么区间分三种:跨越(pos),在([l,pos-1])中,在([pos+1,r])中。

([pos+1,r])为例。先用单调栈预处理(g(i)=sum_{j=1}^imax_{k=j}^ia_k)。那么([1,i])的答案即为(sum_{j=1}^ig(j)).

([1,r])的答案减去([1,pos])的答案即为右端点在([pos+1,r])中的所有子区间最小值之和,我们再容斥掉左端点在([1,pos])右端点在([pos+1,r])的部分:因为(pos)([l,r])的最小值,(forall pos<ile r,s_i>s_{pos}),所以容斥掉的部分就是(g(pos) imes (r-pos)).

RMQ可以ST表或分块ST表(或标准RMQ,若你愿意)。复杂度(mathcal O(nlog n+Q))(mathcal O(n+Q))

My code

T3 背包++

法一:

(f(i,j,k))表示考虑前(i)个物品,体积为(j)能否由(k)种物品拼成。

[f(i,j,k)=f(i-1,j,k)OR_{x=1}^cf(i-1,j-1,k-vx) ]

暴力转移+bitset压位可以做到(O(n^4/omega))

将所有(mod v=p)(k)一起考虑。实际上就变成询问若干段区间的bitset的or的结果(开始一些区间长度不足(c),之后全为(c))。每(c)位设一个关键点,处理前面(k)个bitset的or的结果和后面(k)个bitset的结果,查询就找一个最近的关键点查询。

复杂度(mathcal O(n^3/omega)).

My code

原文地址:https://www.cnblogs.com/oierwanhong/p/14180063.html