T3恶心死我了写了182行4.6K。
T1
联赛状压题。
我们发现(m)很小,那么状压。
设(f[i][j][S])为第(i)个元素使用了(S)集合中的操作之后大小为(j)的概率。
那么我们可以写出转移方程。
设(dp[i][j][S])为前(i)个元素使用了(S)集合中的操作之后,最大值的大小为(j)的概率。
相当于是一个多维背包计数。
那么有转移方程:
然后这个复杂度就是(O(nm^2c^23^m+nm^2c^22^m))。
很卡常
然后我是个毒瘤做题人,有一些卡常技巧。
首先,可以用(long long)存储,取模次数减少一半。
第一个状压(f)的时候,我们发现转移顺序并不影响答案,所以我们可以每次枚举最高位转移,常数减小得多。
还有一个地方,我们枚举不一定要枚举到(mc),可以枚举到(num[s]c)。
T2
结论题。
我们考虑构造答案最小的数据。
必然是全局每个格点占满关键点。
那么这种情况只能留下一行或者一列的白色格子。
那么周长最多是:(2(max(h,w)+1))
这个东西是大于:(2(frac{h}{2}+frac{w}{2})=h+w)的。
那么我们可以发现,我们的最终矩形必然是过中线的。
那么维护一个线段树。
我们考虑扫描线。
当扫描到某一个位置(r)的时候,线段树上下标(l)维护的是([l,r])这一段中大于(h/2)的最小的(y),和小于等于(h/2)的最大的(y)。
考虑动态维护这个东西。
我们发现,随着区间([l,r])的变大,上下的区间从(h)变小。
然而我们的(r)在向右,所以每个(l)位置的上下区间大小都是变小的。
那我们考虑用一个单调栈来维护这个东西。
每一个栈上的位置都在退栈的时候,更新一下自己的区间,什么是自己的区间,就是当自己为最大值或者最小值的那一段区间。
这一段区间中全部都减掉当前缩小的上下区间长度。
由于我们的(r)是变化的,所以初值可以变成(h-l),然后最终求值的时候给答案加上(r)即可。
T3
恶心的(ddp)。
我是从链的情况一步一步推出非链的情况的,貌似和题解推的差不多。
这里我自己推一次。
其实(ddp)最重要的就是构造矩阵,剩下的就是一个差量更新,毫无技术含量就是难写的要死。
那先说一下链的情况。
首先有:
设(dp[i][j])为(i)位置是长度为(j)的链顶端的最大剖分。
设:(f[i]=maxlimits_{j=1}^{L}dp[i][j])
那么设矩阵:
那么有:$$R[i]=G[i]R[i+1]$$
这样我们直接用线段树来维护。
修改的时候单点修改,查询全局矩阵就可以了。
尝试构造树上的情况。
设:
(ch[x])为节点(x)的重儿子。
(son[x])为节点(x)的儿子集合。
(dp[x][i])为树上节点(x)为长度为(i)的链的顶端的子树最优剖分。
(f[x]=maxlimits_{j=1}^{L}dp[x][j])
那么有(dp)的转移:
设(g)为轻儿子的一些贡献。
那么开始构造矩阵:
那么有:
考虑一下这个(G)矩阵究竟是怎么搞的。
第一行,我们把(dp[x][1])的转移搞好,相当于在求出他们的最大值。
第(i(i>1))行,我们把(dp[x][i])的转移搞好,相当于在求出:
中的最大值。
这样的转移也符合我们的(dp)转移方程。
那么我们只需要套一个(ddp)的板子,然后求(g[x][2……L])的时候用(set)来维护一下就行了。
这样复杂度就是(O(qL^3log^2n))