如果有同学需要我的代码的话可以私我要,题面也可以私
当然由于本人很菜,代码和做法不一定是对的,但是一定是过了自己造的对拍
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内跑出极限数据