Codeforces Div. 1 做题记录。
如果一场比赛做完了大部分题会单独开文章发题解,否则暂时写在这里。
暂定从中考后的Codeforces Round #572开始。
比赛按时间顺序而非题号顺序排列。
1188 - Codeforces Round #572 (Div. 1) [5/5]
题解: https://www.cnblogs.com/suncongbo/p/12697816.html
1190 - Codeforces Round #573 (Div. 1)
1178 - Codeforces Global Round 4 [1/8]
G
首先拆绝对值,分成 (b) 全正和全负分别维护下。
使用 DFS 序之后问题就转化成了:你有两个序列 (a,b),每次给 (a) 区间加一个正数,或者询问 (a_ib_i (iin[l,r])) 的最大值。
使用 EI 在 UOJ 介绍的方法 即可。
时间复杂度 (O(nlog^2n+qlog^3n)).
代码: 75866833
1198 - Codeforces Round #576 (Div. 1) [2/6]
A
省略
B
省略
1205 - Codeforces Round #580 (Div. 1) [2/6]
B
显然若某一位上有(3)个数,那么就会形成环,答案为(3). 因此该图点数不超过(2log Ale 120), 边数也是(O(log A))级别。
然后就要求一个新图的最短环,这个可以枚举环上的一条边,然后删掉这条边,求两端点的最短路。
时间复杂度(O(n+log^2 Aloglog A))
代码: 59195761
C
题解: https://www.cnblogs.com/suncongbo/p/11389254.html
1214 - Codeforces Round #583 (Div. 1 + Div. 2)
1209 - Codeforces Round #584 (Div. 1 + Div. 2) [1/8]
E
原问题可以转化为,每列轮换后每行选一个数,使得总和最大。
设(dp[i][S])表示前(i)列已选的行的集合是(S), 枚举轮换状态进行转移。提前求出这一行每个子集在所有轮换中的和的最大值即可得到一个时间复杂度为(O((3^n+2^nn^2)m))的算法,可以通过E1题。
有个性质是只有按列最大值从大到小排序后的前(n)个列是有用的,因此只需考虑前(n)列。
时间复杂度(O(3^nn+2^nn^3+nm+mlog m))
代码: 60827873
1220 - Codeforces Round #586 (Div. 1 + Div. 2) [1/7]
E
以起点为根建DFS树,对于所有子树内没有任何一条返祖边指向子树外的子树,我们无法获得它内部的点权,但是可以获得其内部最大权垂直链的点权,而其他点的点权都可以获得,因此答案就是所有这种子树的内部最大权垂直链的最大值加上其余点的点权和。
时间复杂度(O(n+m)).
代码: 60831008
1229 - Codeforces Round #588 (Div. 1)
1240 - Codeforces Round #591 (Div. 1)
1237 - Codeforces Global Round 5 [5/8]
A
省略
B
省略
C
考虑二维怎么做: 按(x)排序,把每个(x)的点两两配对,消到只剩最多一个。然后相邻的配对,显然不会有相交。
三维就先按(z)排序,对每个二维平面执行二维算法,消到只剩最多一个。然后相邻的配对,显然也不会有交。
时间复杂度(O(nlog n)).
代码: 62854906
D
显然答案要么全是(-1), 要么全都不超过(3n). 将数组复制(3)倍,预处理(r_i)表示第(i)个点后面第一个小于其一半的位置,则某个点能延伸到的最远点就是上述数组的后缀最小值,减去该点的原始位置就是答案。
也可以对每个点二分然后用数据结构实现。
时间复杂度(O(nlog n)).
代码: 62725216
E
树的形态是一棵满二叉树下面挂若干个儿子,且要求每个点的左儿子的右儿子大小为奇数,右儿子的左儿子大小为偶数。那么考虑在两棵深度相同的树上加一个根合并起来,右儿子的左端点个数奇偶性会限制右儿子最左边的链上左儿子的有无,归纳易证只有左儿子最左边的链上儿子可有可无,其余的方案是确定的,答案一定为(0)或(1), 且对于一种深度,只有两个相差(1)的(n)答案是(1).
考虑生成答案为(1)的集合,归纳可证每次将两个数同时加上两数中的偶数(+1),就可以得到下一层的两个数。
时间复杂度(O(log n)).
代码: 62864619
1239 - Codeforces Round #594 (Div. 1)
1246 - Codeforces Round #596 (Div. 1) [4/6]
A
显然答案不超过(log n). 枚举答案,转化为(k)个(2)的幂次和为(n-ak). 求出最少需要几个(( ext{bitcnt}(n-ak)))和最多需要几个((n-ak)),若(i)介于两数之间则可以。
时间复杂度(O(log n))或(O(log^2n)).
代码: 63769126
B
把一个数看作长度为(10^5)的数组,第(i)个位置若(i)不是质数则为(0), 否则为这个质数的幂次(mod m). 将这个数组用(m)进制进行Hash并插入map
中,在map
中查询其每一位取负后的Hash值。
时间复杂度(O(nsqrt n))或(O(nlog n)).
代码: 63771856
C
某个位置的操作不会影响在它右下方的矩形。
设(f[i][j])表示从((1,1))到((i,j))且在((i,j))点由朝右转向朝下的方案数,(g[i][j])表示从((1,1))到((i,j))且在((i,j))由朝下转为朝右的方案数。
则有转移方程: (f[i][j]=sum^{j-1}_{k=lf[i][j]}g[k][j], g[i][j]=sum^{i-1}_{k=lg[i][j]}f[i][k]), 其中(lf[i][j])等于最大的(k)使得(sumx[i][k+1]le n-k), (sumx[i][j])是第(i)行(j)处的后缀和,(lg)同理。这两个数组可以(O(nm))双指针预处理,前缀和优化DP即可。
更简单的实现方式: 从后往前DP, 这样无需处理(lf)和(lg), (lf[i][j])直接等于(m-sumx[j]-1).
时间复杂度(O(nm)).
代码: 63768042
D
题解: https://www.cnblogs.com/suncongbo/p/11768950.html
1242 - Codeforces Round #599 (Div. 1)
1254 - Codeforces Round #601 (Div. 1) [1/5]
C
题解: https://www.cnblogs.com/suncongbo/p/11994646.html
1261 - Codeforces Round #602 (Div. 1)
1264 - Codeforces Round #604 (Div. 1) [1/6]
C
题解: https://www.cnblogs.com/suncongbo/p/11996219.html
1276 - Codeforces Round #606 (Div. 1) [4/6]
A
twone
删o
, 否则删中间那一个即可。
时间复杂度(O(n)).
代码: 66841692
B
建圆方树,统计经过两个点的点对数目即可。以第一个点为根建可以降低代码量。
时间复杂度(O(n)).
代码: 66848795
C
题解: https://www.cnblogs.com/suncongbo/p/12041672.html
D
题解: https://www.cnblogs.com/suncongbo/p/12072371.html
1280 - Codeforces Round #607 (Div. 1) [5/6]
A
显然一次操作只会往原串后面加字符。直接模拟前(m)位,后面的计算即可。
时间复杂度(O(n+m)).
代码: 66904577
B
显然答案是(0,1,2,3,4)或无法完成。如果所有的都是A
就是(0), 所有的都是P
是无法完成,第一行、第一列、最后一行、最后一列中至少有一个全是A
就是(1), 四角的至少一格或者中间的至少一行或一列为A
则是(2), 与边界相邻的格子中有至少一个A
就是(3), 否则为(4).
时间复杂度(O(nm)).
代码: 66912353
C
求最小: 显然答案的下界是所有两端子树大小为奇数的边的边权之和。考虑转换为有根树后每个点奇数的儿子的随意匹配即可达到下界。
求最大: 显然答案的上界是所有边两端子树大小最小值之和。通过重心(点或边)的不同子树内任意匹配容易证明可以达到上界。
时间复杂度(O(n)).
代码: 66919108
D
设(f[u][i])表示(u)子树内分成(i)个连通块最多有多少个正的,(g[u][i])表示(u)子树内分成(i)个连通块,在保证正的个数最多的前提下根节点所在连通块点权和最大是多少。背包转移即可。由于根所在的连通块最多产生(1)的影响,因此优先保证(f[u][i])最大是正确的。
时间复杂度(O(n^2+nm)).
代码: 66959746
E
首先对于一个电路来说,等效电阻与电路中所用电阻值之和成正比。那么对于一个串联电路,我们最优策略一定是贪心地选择最小的儿子去分担全部等效电阻。这就意味着答案一定是若干并联嵌套的结构。而且并联之间的嵌套没有意义,就相当于一层所有电阻并联的并联电路,因此所有电阻均分阻值即可。做法就是先建树然后树形DP(串联求最小值并联求和)求出最少用多少个电阻,然后均分阻值。
时间复杂度(O(n)).
代码: 66977391
1266 - Codeforces Global Round 6
1268 - Codeforces Round #609 (Div. 1)
1270 - Good Bye 2019 [6/9]
A
显然拿到最大牌的一定能赢。
时间复杂度(O(n)).
代码: 67883026
B
若所有相邻数差的绝对值都不超过(1)则无解,否则输出任何相邻的即可。
时间复杂度(O(n)).
代码: 67887588
C
做法一:
设已有数的和为(x), 异或和为(y), 则在后面加(y)和((x+y))两数即可。
时间复杂度(O(n)).
做法二:
首先考虑假设有两数(a<b)且奇偶性相同, 则三个数(frac{b-a}{2},frac{b-a}{2},a)满足和为(b)且异或和为(a).
令(X=10^{15}), 则构造三个数使和、异或和分别为(2X-a,X ext{xor} b)即可。
时间复杂度(O(n)).
代码: 67899122
D
做法一:
进行((k+1))次询问,第(i)次询问前((k+1))个数中除了第(i)个数之外的数。那么所有答案中最小的就是前((k+1))个中的第(m)大,结果不等于该数的一次询问就产生了一个小于第(m)大的位置,统计即可。
询问次数(k+1).
做法二:
首先进行((n-k+1))次询问,初始集合为([1,k]), 每次删掉第(m)大的元素,添入下一个元素。到最后集合中还剩下的元素就是整个序列的前((m-1))小、前((k-m))大以及中间的一个元素,集合外的元素都被确定,且我们确定了至少(2)个元素。对于集合内的每个元素,询问集合内去掉这个元素再加上已确定的任意(2)个元素。若答案为(2)个元素中的较小者,则该数属于前((k-m))大;否则该数属于前((m-1))小。
询问次数(n).
代码: 67917565
E
首先考虑最一般的情况,将横纵坐标异或值为偶数的点放入集合(1), 为奇数的点放入集合(2), 那么一定满足同集内距离为偶数,异集内距离为奇数。
但是存在特殊情况,这种方法无法划成两个非空集合。首先将所有点减去第(1)个点,令(g)为操作后所有点横纵坐标绝对值的(gcd), 将所有点横纵坐标全部除以(g). 若此时仍分不开,那么一定所有点的坐标都是同奇或同偶,且两种点都存在。那么直接将同奇同偶各分一组,这样同组内距离的平方是(8)的倍数,而不同组内距离模(4)余(2).
时间复杂度(O(n)).
代码: 67998439
G
令(b_i=i-a_i), 则对任意(i)有(1le b_ile n), 我们就是要找一个集合(S)满足(sum_{iin S}(i-b_i)=0).
设(i)向(b_i)连一条边,则形成一棵基环树,至少有一个环,直接输出环上元素即可。
时间复杂度(O(n)).
代码: 67949067
1284 - Hello 2020 [5/7]
A
省略
B
省略
C
省略
D
显然相当于判断是否有两个元素在A中和B中是否交的情况不同。对于一个元素(i),考虑所有(ra_j<la_i)的元素(j), 假设有一个序列初始均为(0), 我们把([lb_j,rb_j])这个区间的值(+1), 执行完所有的(j)之后求([lb_i,rb_i])之和,不为(0)就说明存在一个元素在A中在(i)前面且无交,在B中和(i)有交,否则没有。那么我们扫描线,把一个元素拆成两个事件,一个是在(ra_i)处修改,一个是在(la_i)处询问,线段树维护区间加区间求和,这样求出了A中有交B中无交的情况;再交换A和B,重新做一遍即可。
时间复杂度(O(nlog n)).
代码: 68191145
E
题解: https://www.cnblogs.com/suncongbo/p/12575009.html
1286 - Codeforces Round #612 (Div. 1) [4/6]
A
DP即可。
时间复杂度(O(n^2))或(O(n^3)).
代码: 68252921
B
考虑让所有权值构成(1)至(n)的排列,从下往上处理每一个子树,合并儿子的时候只需要保证每个儿子内的点相对顺序不变,因此给儿子定一个任意顺序,给每个儿子的子树内点加上在它前面的儿子的子树大小和即可。然后插入根,子树内除了比根小的前若干个之外权值都(+1), 根的权值定为比它小的个数(+1)即可。
时间复杂度(O(n^2)).
代码: 68258103
C
题解: https://www.cnblogs.com/suncongbo/p/12165202.html
D
首先最先碰撞的肯定是相邻的两个球。那么可能的碰撞时间有不超过 (2(n-1)) 种:对于每对相邻的球有“左边向左右边向右”和“同左同右中的一种”。
于是从小到大枚举这些事件,在第 (i) 个事件结束的概率就等于前 ((i-1)) 个事件均未发生的概率减去前 (i) 个事件均未发生的概率。考虑维护目前的限制中的事件均未发生的概率。
使用线段树即可。线段树每个节点存储左端点和右端点的方向,像矩乘那样合并即可。
时间复杂度 (O(2^4nlog n)) 或 (O(2^3nlog n)).
代码: 74251533
1292 - Codeforces Round #614 (Div. 1)
1290 - Codeforces Round #616 (Div. 1) [4/6]
A
省略
B
首先如果询问的串首尾不同,那么可以把和尾相同的字符全都移到首,显然任何一个真前缀中和尾相同的字符数量大于原来,答案是YES
.
如果首尾相同,若整个串出现了至少三种不同的字符,那么任取两种不同于首尾的字符,假设为b
和c
,并不妨假定存在一个b
在一个c
前面出现。可以把所有的b
挪到尾,所有的c
挪到首,这样右端点在原序列b
第一次出现位置及之后的所有前缀b
的数量一定少于原来,左端点在原序列c
最后一次出现位置之前的所有前缀c
的数量一定大于原来,二者并一定是整个串,答案为YES
.
否则,若只有一种字符显然为NO
; 若有两种不同字符,设为a
和b
且首尾为a
,考虑前缀b
出现次数在原序列中从(0)变化到(cnt_b), 新序列从(0)或(1)递增变化到(cnt_b-1)或(cnt_b), 一定存在一个位置二值相等,答案为NO
.
时间复杂度(O((n+q)S)).
代码: 70049896
C
显然每个集合会被操作(0)次或(1)次。考虑一个灯泡的实质是对包含它的集合操作次数进行了限制,形如“某个集合必须选”、“某个集合必须不选”、“某两个集合必须都选或都不选”、“某两个集合中必须恰好选一个”。每个集合拆成选和不选两个点使用并查集维护即可,详见代码。
时间复杂度(O((n+m)alpha(m))).
代码: 70075591
D
考虑一个询问次数(frac{2n^2}{k})的暴力,将序列分为长度相等的段,每段长为(frac{k}{2}),然后枚举(i<j), 依次加入第(i)段和第(j)段的所有元素,就可以知道每个位置前面是否有和它一样的。
优化一下这个过程,发现每次问完两段之后都pop
出来很废,于是我写了个一个比较垃圾的(frac{3n^2}{2k})的做法,每次以固定的间隔进行询问(先问((1,2),(2,3),(3,4),...,(n-1,n)),然后((1,3)(3,5)(5,7)...(n-3,n-1))和((2,4)(4,6)(6,8)...(n-2,n)),然后再问间隔为(3,4...))
实际上这就相当于一个DAG竞赛图,将其划分为若干条路径,一条长度为(l)的路径需要询问(frac{k}{2}(l+1))次。划分出的路径相交是不优的,因为出现这种情况可以在中间进行断裂。假设划分成(c)条不交路径,则贡献为(frac{k}{2}(frac{m(m-1)}{2}+c)), 其中(m=frac{2n}{k}).
官方题解给出了一个询问次数(frac{n^2}{k})的算法,考虑把序列分段每段长度为(k),然后按照UOJ #460那样的顺序去筛,每次只用还未被筛掉的筛。这样可以保证每个元素会被其余所有块内位置和它一样或比它靠后的元素以及它所在的块内位置比它靠前的元素筛掉,且只用还未被筛掉的筛保证了不会出现两个元素互相筛导致漏算的情况。因此每一种数只会被计算一次(这里的确比较模糊,目前还没完全理解)。
代码: 72506823
1299 - Codeforces Round #618 (Div. 1)
题解: https://www.cnblogs.com/suncongbo/p/12933661.html
1307 - Codeforces Round #621 (Div. 1 + Div. 2)
1314 - Codeforces Round #623 (Div. 1) [6/6]
题解: https://www.cnblogs.com/suncongbo/p/12864397.html
1320 - Codeforces Round #625 (Div. 1) [5/6]
A
把(a_i)变为(a_i-i)然后统计众数即可。
时间复杂度(O(n)).
代码: 72167217
B
先求最短路,每个时刻如果下一个点最短路大于当前最短路(-1)则必须改,如果当前点的出点除下个点之外存在等于当前最短路(-1)的则可以改。
时间复杂度(O(n+m))或(O(n+mlog n)).
代码: 72177172
C
从小到大枚举选的(x), 相当于给一个有初始值的数组后缀加一个数以及询问全局最大值,线段树维护即可。
时间复杂度(O(nlog n)).
代码: 72193245
D
操作相当于把0
的位置向左或向右移动(2)且移动路径不能相交,将01
串变成“相邻两个(0)之间有多少个(1)”的形式,那么两个序列可达当且仅当转变后的每个位置模(2)对应相同。Hash即可。
时间复杂度(O(n+q)).
代码: 72205619
E
建虚树,不难发现一个节点的答案一定是初始点到它路径上不经过其他颜色初始点的颜色中,距离除以扩散速度上取整的值最小的,若有多个取颜色编号最小的。顺便发现若一个点不是初始点,则该点的答案一定来自于周围点的答案。在虚树上两次 DFS 树形 DP 即可。
时间复杂度 (O((n+sum k_i+sum m_i)log n)).
代码: 78533377
1305 - Ozon Tech Challange 2020 (Div. 1 + Div. 2) [6/8]
A
分别排序输出即可。
时间复杂度(O(nlog n)).
代码: 72312863
B
很容易判掉答案为(0), 否则一定存在一个位置满足左边(
的个数等于右边)
的个数,答案为(1),输出即可。
时间复杂度(O(n))或(O(n^2)).
代码: 72321525
C
所有数(mod m)后若有相同的则答案为(0),否则显然数不超过(m)个,暴力即可。
时间复杂度(O(n+m^2)).
代码: 72318873
D
每次询问两个叶子并删掉,若询问返回值为其中之一则根为返回值,否则删掉之后一定不会产生任何影响。
询问次数(lfloor frac{n}{2}
floor), 时间复杂度(O(n^2)).
代码: 72329243
E
首先(m)最大的情况是令(a_i=i). 考虑单个元素的贡献,最大的元素每增加(2),贡献少(1). 从(n)开始,若当前的比目标多的对数为(m'), 假设(m'-lfloorfrac{i-1}{2}
floorge 0)则直接删去(i) (怎么删后面讲),否则通过增加(a_i)来减少对数,(a_i)每增加(2)对数减少(1). 删除元素可以通过令(a_i=i imes C_1+C_2)来实现,其中(C_1=2 imes 10^4,C_2=5 imes 10^8).
时间复杂度(O(n)).
代码: 72347379
F
题解: https://www.cnblogs.com/suncongbo/p/12555523.html
1322 - Codeforces Round #626 (Div. 1) [5/6]
A
省略
B
做法一样的原题: atcoder ARC092D
考虑从大到小枚举每一位 (k),求有多少对 ((i,j)) 满足 ((a_i+a_j) ext{and} 2^k=2^k).
将所有数对 (2^{k+1}) 取模。枚举 (i), 那么可得 (a_i+a_jin [2^k,2cdot 2^k)cup [3cdot 2^k,4cdot 2^k)). 二分即可。
时间复杂度 (O(nlog nlog W)).
代码: 72646262
C
因为 (gcd(a,b)=gcd(a,a+b)), 容易发现只需要把右边的点按和左边相连的点集分类,每一类内点权求和,不同类求 (gcd). 随机权值异或 Hash 即可通过。
时间复杂度 (O(nlog n+log W)).
代码: 72651484
D
题解: https://www.cnblogs.com/suncongbo/p/12561232.html
E
直接使用中位数二分转成 (01) 的那个套路,发现初始序列的每一个 (01) 交替的连续段的前一半都会变成左边的数,后一半都会变成右边的数。
那么从小到大每次把一个初始序列位置变成 (0),维护最终序列的变化。显然最终序列每次只会有若干元素由 (1) 变 (0),而不会由 (0) 变 (1),因此可以使用并查集维护下一个没变 (0) 的位置,实现每次将一个区间覆盖为 (0). 然后使用 set
维护连续段,每次在连续段发生变化时按照上面的结论重构该连续段对最终序列的影响即可。
时间复杂度 (O(nlog n)).
代码: 78501168
1326 - Codeforces Global Round 7 [6/7]
A
构造数 (233333...) 即可。
时间复杂度 (O(n)).
代码: 73663517
B
按题意模拟即可。
时间复杂度 (O(n)).
代码: 73667903
C
最大值显然是 (sum^n_{i=n-k+1}i), 方案数直接把相邻两个必选点之间的点数相乘即可。
时间复杂度 (O(n)).
代码: 73675204
D
容易证明让前缀匹配得最多一定更优。贪心匹配前缀和后缀,删掉之后剩下的部分用 Manacher 算法求最长回文前缀和最长回文后缀即可。
时间复杂度 (O(n)).
代码: 73701164
E
考虑给定了一个数 (x) 以及在哪些位置需要操作 (也就是当前处理的前缀 (q_i)),如何判断答案是否大于等于 (x): 从左到右扫同时维护 (ge x) 的个数 (c),在某个位置依次执行:若该数 (ge x) 就令 (cleftarrow c+1), 若该时刻要删最大值则令 (cleftarrow max(c-1,0)),最终若 (c>0) 则答案 (ge x). 那么不考虑和 (0) 取 (max), 单纯维护 (+1/-1) 的前缀和,等价于总和大于每个位置前缀和的最小值。
那么对于原问题,从大到小枚举答案,线段树维护即可。
时间复杂度 (O(nlog n)).
代码: 73718802
F
题解: https://www.cnblogs.com/suncongbo/p/12792845.html
1329 - Codeforces Round #631 (Div. 1) [5/5]
题解: https://www.cnblogs.com/suncongbo/p/12789094.html
1338 - Codeforces Round #633 (Div. 1) [5/5]
题解: https://www.cnblogs.com/suncongbo/p/12779121.html
1336 - Codeforces Round #635 (Div. 1) [5/6]
A
把一个点搞成“工业的”称作“选”。显然选一个点必须选他的所有儿子,于是价值就是 (dep-sz+1),贪心即可。
时间复杂度 (O(n)) 或 (O(nlog n)).
代码: 76829840
B
直接枚举 (x,y,z) 的中位数在另外两个序列里二分即可。
时间复杂度 (O(nlog n)).
代码: 76844830
C
设 (f[l,r]) 表示当前产生了 ((r-l+1)) 个字符,匹配 B 串区间 ([l,r]) 的方案数。对于位置 (gt m) 的就当成通配符即可。
时间复杂度 (O(n^2)).
代码: 76871889
D
假设第 (i) 个位置有 (a_i) 个。则插入 (i) 之后 triplets 和 straights 的增量分别为 (frac{a_i}{2},a_{i-1}a_{i+1}). 如果初始时 (a_ige 2),则插入一个 (i) 就可以得到结果。现在的问题就在于分辨 (0) 和 (1).
假设依次询问 (1,2,3,...,n). 则 straights 的增量依次为:
(Delta_1=a_2a_3)
(Delta_2=(a_1+1)a_3+a_3a_4)
(Delta_3=(a_1+1)(a_2+1)+(a_2+1)a_4+a_4a_5)
(Delta_i=(a_{i-2}+1)(a_{i-1}+1)+(a_{i-1}+1)a_{i+1}+a_{i+1}+a_{i+2}) ((3le ile n-2))
(Delta_{n-1}=(a_{n-3}+1)(a_{n-2}+1)+(a_{n-2}+1)a_n)
(Delta_n=(a_{n-2}+1)(a{n-1}+1))
由于 (a_1+1+a_4lt 0),我们可以通过 (Delta_2) 解出 (a_3). 但是其余的看起来无从下手。注意由 (Delta_1) 和 (a_3) 不能解出 (a_2),因为 (a_3) 可能等于 (0).
下面题解给了两种做法:
做法一:
容易发现如果我们知道了 (a_1,a_2,a_3) 的值,整个问题就很容易解决了。于是我们再问一次 (1). (先不考虑次数限制)
(Delta'_1=(a_2+1)(a_3+1))
由于 (a_3+1gt 0),很容易解出 (a_2) 的值。而且因为对一个位置询问两次可以通过 triplets 确定该位置的值,所以 (a_1) 也知道了!
于是一个一个解下去就可以了。最后一个方程 (Delta_n) 是废的,因为通过 (Delta_i) 可以得出 (a_{i+1}) 的值,所以只需 (n) 次询问。
做法二:
在 ((n-2)) 和 (n) 之间再插入一次询问 (n),并把这次询问记作 (Delta_n),最后一次记作 (Delta'_n). 则
(Delta_n=(a_{n-2}+1)a_{n-1})
(Delta_{n-1}=(a_{n-3}+1)(a_{n-2}+1)+(a_{n-2}+1)(a_n+1))
(Delta'_n=(a_{n-2}+1)(a_{n-1}+1))
和上面同理,可以解出 (a_n,a_{n-1},a_{n-2}). 顺着推回去就行了。注意对 (1) 的询问是废的。
询问次数 (n).
代码: 77060778
E
题解:https://www.cnblogs.com/suncongbo/p/12768044.html
1340 - Codeforces Round #637 (Div. 1) [4/6]
A
直接模拟,用 set 或者链表或者并查集维护一下每个位置后面第一个没被选的位置。
时间复杂度 (O(n)) 或 (O(nlog n)).
代码: 77790241
B
对每个位置算出它改成每个值要 turn on 几个位置(或者改不成),然后背包。
时间复杂度 (O(n^2S)). ((S=10))
代码: 77811119
C
设状态 ((u,x)) 表示在 (u) 点时间 (mod g=x),则建图跑 01-bfs 即可。朴素的方法边数是 (O(m^2g)) 的。
显然一条路径每次经过的都是数轴上相邻的两个点,所以只需要每个点向相邻的两个点连边。
时间复杂度 (O(mg)).
代码: 77900162
D
显然答案的下界是 (max^n_{i=1} du[i]) (度数)。对于该下界可以完成构造。
我们让每个点进去的时间等于出来的时间 (-1) 即可。定义过程 (F(u,x)) 表示在 (x) 时刻第一次到达点 (u)。考虑 (u
e 1),那么对于儿子 (v) 每次递归调用 (F(v,x+1)),则最后一次到 (v) 的时刻是 (x),回到 (u) 的时刻为 (x+1). 这种情况下最后离开 (u) 的时间为 (x+du[u]-1)。在这之间肯定有一个时刻满足 (x=du[u]),在这个时刻把时间改小变为 (0) 即可使得最后的时间为 (x-1). 若 (u=1),那么初始时 (x=0),每次调用一个儿子,没有必要作任何特殊处理。
时间复杂度 (O(n)).
代码: 77874941