Codeforces Round 943 (Div. 3) D-G2
Codeforces Round 943 (Div. 3)
1968D-枚举
思路:
每个人走的位置最多会形成长度为n的环,所以直接枚举走到某个位置之后后面就不走了的所有情况的最大值,相互比较即可
点击查看代码
1968E-构造
题意:
设\(F(A_i,A_j)=|x_i-x_y|+|y_i-y_j|\),在\(N*N\)的矩阵中选n个点使所有不同的\(F(A_i,A_j)=|x_i-x_y|+|y_i-y_j|\)数量最多
思路:
在\(N*N\)中曼哈顿距离的范围为\([0,2*(n-1)]\),如果全放对角线,那么能得到的曼哈顿距离全是偶数且是范围内的所有偶数,能不能改变一些位置之后把奇数进去?可以发现如果将一个点和相邻的一个点行或列相同,则他们的曼哈顿距离会-1,然后这个点与其他点的曼哈顿距离也都减了1或加了1,可以构造出奇数来。
1968F-枚举 二分
点击查看代码
题意:
如果一个数组可以分成大于等于2的连续子数组,每个连续子数组的异或和都相等,那么这个数组叫做好数组
给一个长度为n的数组,给出q个询问,每次询问给出L,R,问能否数组\([L,R]\)是不是一个好数组
思路:
要算连续子数组的异或和,考虑用前缀异或和维护,
对于\([L,R]\)的数组,如果总的异或和是0,那么总能在中间找到一个分界点使左右两边相等,
如果总的不为0,那分出的字段应该是奇数个,不可能为偶数个,如果为偶数个总的异或和应该为0。如果为奇数个那么三个段其实就够了,因为如果分的段数大于3是可以变成3段的,比如五个段TTTTT,对于中间三个T,合并之后异或和为T,就变成了TTT,考虑三个段的情况,设第一段的右端点为X,第二段的右端点为Y,则整个序列为\(L--X--Y--R\)
那么L<=X<Y<R,如何找到X,Y的位置? 对于2、3段来说,总异或和为0,也就是说\(s[R]\oplus[X]==0\)即\(s[R]=s[X]\)
同理\(s[L-1]=s[Y]\),保存相同\(S[i]\)的下标然后二分查找
点击查看代码
1968G1-z函数 二分
题意:
定义\(F_k\)表示将字符串S分成k个连续子串的所有方案的\(LCP(w_1,...,w_k)\),\(LCP(w_1,..,w_k)\)表示字符串\(w_1,...w_k\)的最长公共前缀的长度,给定一个字符串\(S\)和\(l,r\),G1中\(l=r\),求出\(F_l,...F_r\)
思路:
z函数可以表示\([i,n]和[1,n]\)的最长公共前缀,二分出最小的不能满足分成k段的最长公共前缀的长度,那么答案就是\(二分结果-1\),表示最大的分成k段的最长公共前缀的长度,对于二分的check来说,只要该位置的\(z[i]大于等于mid\),就将\([i,n]\)段分成\([i,i+mid-1]和[i+mid,n]\),这样保证分的子段数量最多
点击查看代码
1968G2
思路:
考虑二分的过程,是向后一位一位找到>=mid的位置然后来划分,如果能处理所有等于>=mid的z值的下标再二分找则效率更高,那么对于当前的能分的段数cnt,\(F_{cnt}=mid\),因为要保存>=mid的z值下标,所以LCP从大到小枚举,而对于F来说,分的子段数量越大,LCP的值越小,所以将LCP从n枚举到1,记录\(F_{cnt}\)后,再用大的cnt更新小的cnt。
点击查看代码

浙公网安备 33010602011771号