PKUSC2021 简要题解

如果有同学需要我的代码的话可以私我要,题面也可以私

当然由于本人很菜,代码和做法不一定是对的,但是一定是过了自己造的对拍


D1T1 Sum Transformation

假设原矩阵第(i)行的和是(a_i),第(j)列的和是(b_j),整个矩阵的和是(S)

那么变换一次以后((i,j))的位置就会变成(a_i+b_j)

考虑变换的第二次,简单推导一下,((i,j))位置就会变成(n(a_i+b_j)+2S)

不难发现,((i,j))位置的值一定可以用(p(a_i+b_j)+q)来表示,这个系数对于每一个位置是相同的

这个系数显然可以矩阵乘法递推解决

时间复杂度(O(logT+n^2))



D1T2 逛街

如果没有修改,我们发现把每个(i)向最小的(j>i)满足(a_j>a_i)连边(找不到就往(n+1)连),这样会得到一棵树

在树上倍增就可以回答询问

注意到所有的相同的数一定是连成一段的

有修改就意味着一些数可能被覆盖掉,消失了

也就是树上的一些点被删掉了


先考虑sub2,所有修改是对于全局的

不难发现这样我们的删除只会删除叶子

考虑反证法,如果我们修改中删去了一个非叶子节点,那么由于是全局修改,它一定会往它的儿子扩展一步,它就出现在了新的位置,矛盾

于是询问([l,r])我们就只需要在(l)处找到树中祖先上第一个还存在的节点,再倍增跳上去,直到跳出当前(r)处的范围即可

找叶子可以用st表求区间最大值的位置


考虑sub3,所有修改是任意的

不难发现这样就可能会删除非叶子节点

但是可以看到的是,树的结构并不会改变,因为一个点它的父亲被删除了,它在树上的新父亲一定是它父亲的父亲,姑且称之为爷爷

证明考虑反证,假设它的父亲是(x),爷爷是(y),能找到的新父亲是(z),那么有(a_y>a_x>a_z)(x<z<y),不难发现此时如果(x)(y)覆盖掉了,由于(z)(x,y)中间,所以(z)也一定被覆盖了,矛盾

所以这棵树是可以一直使用的

我们删除非叶子节点时并不在树上显式地删除它,而是采取一个懒惰删除的方式,只是把他的权值置为(0),查询时查询链和即可

接下来我们还可以证明,尽管可能会删去非叶子节点,但是删去的非叶子节点一定出现在修改区间左端点处

因为只有左端点处的数才不能继续往左扩展,修改区间内部只会删去叶子,这一点的证明跟前面sub2里的证明是类似的


于是一个做法就呼之欲出了

只要我们能够维护每个位置当前的数并支持单点查询,就能够在树上删去非叶子节点的权值,并找到第一个非叶子节点并在树上完成倍增,查询链权值可以用树状数组(O(logn))维护

考虑维护每个位置会对右侧的哪些点取max,不难发现这是一个连续区间,设右端点是(r_i),我们只需维护(r_i)

于是修改([L,R))其实是让(forall i in [L,R) , r_{i}=r_{i+1})

不难发现就是删去(L)这个位置的数,并在(R)这个位置补充一个原来的(r_R)

显然平衡树就是合适的数据结构

总时间复杂度(O((n+q)logn))

代码4.2k,还是挺好写的



D1T3 德州扑克

不会真的有“人”会做吧?



D2T1 一棵树

不删边sb题随便搞

考虑我们删除某条边造成的总贡献

考虑删边后形成的两侧子树A,B中每条边的贡献

对于A中的每条边,他的贡献就是以A中每个点作根,这条边远根处的size之和,再乘上B的size

不难发现我们只需换根dp出以一个点为根,所有点的size和

就可以方便计算出两侧的贡献了

时间复杂度(O(n))

实现细节不少



D2T2 代金券

不难发现一个贪心策略,就是优惠券尽量留在最后来用

发现这样不完全对,优惠券在前面也是可能会使用一部分的,只要不影响获得获得优惠券的数量,也就是(a_i mod c)以内的可以随便用

于是进一步,我们可以归纳出完整的策略

存在且只存在一个(i),满足

对于([1,i-1])中的菜品(j),我们最多用(a_j mod c)张优惠券,并且尽量多用

对于([i+1,n])中的菜品(j),我们能够全部用优惠券支付

对于(i)处的菜品,我们用一些优惠券,再用一部分现金来获得优惠券,使得最后恰好优惠券能用完

同时不难发现这个(i)满足

([i,n])中的菜品全部使用代金券支付的时候代金券不够用

([i+1,n])中的菜品全部使用代金券支付的时候代金券够用

于是我们只需要找到这个(i)即可

因为有修改,暴力维护和查找是(O(nq))

考虑用线段树来维护这个东西

考虑前半部分你对于一个菜品(j),假设你当前有(x)张优惠券

那么你买它之后的优惠券是 (x=max(x-a_j mod c,0))(x+=lfloor frac{a_j}{c} floor) 也就是 (x=max(x+(lfloor frac{a_j}{c} floor - a_j mod c),lfloor frac{a_j}{c} floor))

注意(x=max(x+a,b))这样的标记满足结合律,但是没有交换律

((a,b))((c,d))合并以后就是((a+c,max(b+c,d)))

于是你可以很方便地维护购买一个前缀以后的优惠券数量

所以我们在线段树上二分就能找到分界点(i)

前半部分使用的现金可以用总花费减去用掉的优惠券算出

(i)处使用的现金只需二分即可

总时间复杂度(O((n+q)logn))



D2T3 招新

神仙题我写了三个做法来拍

考虑整数部分和小数部分是可以拆开来计算的

我们可以枚举小数部分的大小关系,来计算整数部分的分配方案

最后除以所有满足(0<x_1<x_2....<x_n<m)的方案即可,这部分显然是(m^n)

具体组合意义的证明可以考虑给小数部分大小排名为(i)的确定一个整数部分,这样分配的方案,排序以后,与上面的方案一一对应


做法1:裸暴力

直接(O(n!))枚举小数部分的大小关系,然后接下来的dp是trivial的

(f[i][j][k])表示讨论了前(i)个数,第(i-1)个数整数部分是(j),第(i)个数整数部分是(k)的方案数

转移前缀和优化下,总复杂度(O(n!nm^2))


做法2:暴力dp

注意到我们的转移只需考虑(i)小数部分与(i-1)(i-2)小数部分的大小关系,并不关心他们在最终的序列中排名究竟是第几

于是我们只需要记在前(i)个数小数部分排名中,他们的相对排名即可

(f[i][a][x][b][y])表示讨论了前(i)个数,第(i)个数小数部分排名是(a),整数部分是(x),第(i-1)个数小数部分排名是(b),整数部分是(y)的方案

(b<a)(y<x),从(f[i-1][b][y][c][z])转移过来时需要满足(c<a and z leq x-K)(c geq a and z leq x-K-1),不难发现这是两个矩形,在固定(b)(y)的时候可以二维前缀和优化

(b>a)时同理

总复杂度(O(n^3m^2)),极限数据约10s,造数据是够用了


做法3:优化dp

注意到上面的dp转移时当(x-y geq K+1)时,任意(z leq y)均满足条件,而(z leq y)是显然的

于是这启示我们只需记录(x-y)的值即可,并且可以把(x-y geq K+1)的合并

修改dp状态

(f[i][a][x][b][y])表示讨论了前(i)个数,第(i)个数小数部分排名是(a),整数部分是(x),第(i-1)个数小数部分排名是(b),整数部分与第(i)个数的差是(y)的方案,其中(y leq K+1)

(0 leq y leq K)转移同上略微讨论

(y=K+1)时是一个整体和,也可以前缀和处理

总复杂度(O(n^3km)),看起来没啥优化

但是请注意当(lfloor frac{n-1}{2} floor k geq m)时答案是(0),可以直接判掉

所以(nk)其实是(O(m))级别的

时间复杂度降为(O(n^2m^2)),可以在2s内跑出极限数据

原文地址:https://www.cnblogs.com/deaf/p/14784559.html