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} \rfloor\) 也就是 \(x=max(x+(\lfloor \frac{a_j}{c} \rfloor - a_j\ mod\ c),\lfloor \frac{a_j}{c} \rfloor)\)
注意\(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} \rfloor k \geq m\)时答案是\(0\),可以直接判掉
所以\(nk\)其实是\(O(m)\)级别的
时间复杂度降为\(O(n^2m^2)\),可以在2s内跑出极限数据