。。。
怎么又改题大神了。
kuku.
T1
我们对于每行的每一个字串计算有多少个子矩形将之容纳并计算为有效贡献。
相当于是对一行的每一个后缀的每一个前缀进行计算。
我们先建trie树。
其上每一个节点代表当前阶段后缀(最一开始的阶段当然是整个串,总共有m个阶段)的不同前缀。
对于每一个节点开一个(set)存一下有哪些行是经过当前串的。
那么对于一个新插入的元素(x),其对答案的总贡献是((x-pre_x)(nxt_x-x))。
这样相当于考虑了只有当前元素而没有其他元素的时候的贡献。
事实上不需要考虑当前元素和(set)中其他元素在一起的贡献。
因为这个贡献已经被之前插入的元素计算过了,因为这些情况下不包含当前元素的方案仍然被计算了1次。
然后我们就可以计算出第一阶段的答案。
其他阶段我们同样额外维护类似的答案即可。
当从这个阶段转移到下一个阶段的时候。
我们对根节点的所有儿子进行合并。
表示不考虑最前面的元素。
这样合并之后把当前答案减去新的到的根维护的set的贡献。
表示之前的贡献不在计算。
这样(Trie)相当于变成了一个及时合并的后缀树。
合并的时候分别的(map)和(set)进行启发式合并即可。
为了方便交换(set),这里我用指针实现。
(set<int> *S,se[maxn];S=&se[++id])
这样写即可。
T2
我们发现一个位置从后向前的与缀和最多分为不同的30段。
于是我们可以利用线段树扫描线进行这个操作,询问按照右端点排序。
当我们加入一个点的贡献的时候。
考虑这个点在某一段的值的贡献,如果与缀和是(K)的倍数就加入贡献。
这样每个位置最多给线段树进行30次的操作。
查询操作是(logn)的区间查询。
我们可以打标记也可以标记永久化。
最终复杂度是(O(n30logn+qlogn))
T3
我们考虑求(dp[i][j])表示(i)个各不相同的数排列中有(j)个是(jm)数的方案数。
那么(dp[i][j]=dp[i-1][j](i-1)+dp[i-1][j-1])。
我们考虑最新加入的元素和之前的元素的大小关系。
可以强制这个元素是最小的元素。
那么最终除了放在序列首位的贡献为(dp[i-1][j-1])之外,放在其他位置均不影响(jm)数的个数。
所以有这样一个递推式。
很容易发现:(dp[i][j]=egin{bmatrix}i\jend{bmatrix})
因为上面的递推式就是第一类斯特林数的递推公式。
下一步统计答案。
这个是什么意思呢?
我们这次枚举最大值所在的位置,左右分别两个长度不同的(jm)序列。
根据具体数学上的斯特林恒等式:
这样我们需要求第一类斯特林数。
怎么求?
我们知道斯特林数是轮换数。
而一个排列是由轮换构成的,所以:
这样就可以倍增求这个东西了。