Codeforces Round 943 (Div. 3) D-G2

Codeforces Round 943 (Div. 3)

origin:https://www.bilibili.com/video/BV1wx4y1z76v/?spm_id_from=333.337.search-card.all.click&vd_source=66ac5da514fe1be9729ebba538a11951

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。

点击查看代码
posted @ 2024-05-14 14:04  Danc1ng  阅读(52)  评论(0)    收藏  举报