「泛做题解」曾经的 AtCoder 题解汇总

Posted cyanic

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「泛做题解」曾经的 AtCoder 题解汇总相关的知识,希望对你有一定的参考价值。

注:此博客写于 2017.8 ~ 2017.11

一个小清新OJ.

题意简短,超赞!

题目新颖,超赞!

解法巧妙,超赞!

标程简洁,超赞!

AtCoder Regular Contest 068

E - Snuke Line 给定(n)个区间([l,r])和一个数(m)。对于(d=1,2,3…,m),求(kd(1 leq kd leq m,kin Z))被多少个不同区间覆盖(对于不同的(k),只算一次)。(1 leq n,m leq 3 imes 10^5,1 leq l leq r leq m)

记区间的长度为(len=r-l+1)。想到可以(O(mlogm))暴力枚举所有的(kd),用线段树算出它被几个区间包含。容易发现当(d<len)时,有可能被多次计算。

考虑当(d leq len)时,则一定存在(k)使得(kd)被这个区间覆盖。于是我们记录满足(d leq len)的区间个数即可。而对于(d>len)的情况,至多有一个(kd)被区间覆盖,于是就可以用线段树维护。即当(d>len)时加入这个区间,同时单点询问(kd)被多少个区间覆盖。复杂度(O((mlogm+n)logm))

Code

F - Solitaire 有一个双端队列,依次往首或尾插入数1到n。然后你可以从队列的首或位取出一个数,顺次相接组成一个序列。求有多少个序列的第(K)位为(1)(1 leq k leq n leq 2 imes 10^3)

显然,当(n)个数全部插入后,队列一定是递减到1再递增的。不难发现,得到的序列的前(K)位,一定是由两个递减序列交错得到的,且第(K)位为1。

(n)(1)逐个考虑每一个数是否选择,且属于哪一个序列。定义(f(i,j)) 已经得到了序列的前(i)位,其中第(i)位为(j)的方案数。将(j)加入序列1,则(f(i,j))可由(f(i-1,k), k>j)转移过来。

如果将新的数加入序列2,该如何转移?可以发现,这个数一定是没选择的数中最大的数(序列2也是递减的)。(f(i,j))可由(f(i-1,j))转移过来。

事实上,DP的过程还有一个非法的转移。(f(K-1,1))会转移到(f(K,1)),不是以1作为第(K)个数。

对于剩下的(n-K)个数,每次可以取头或尾。于是答案(ans=(f(K-1,1)-f(K-1,1)) imes 2^{n-K-1})。 时间复杂度(O(nK))

Code

AtCoder Regular Contest 069

E - Frequency(n)堆石头,第(i)堆有(ai)个石头。每一次,你需要记录下石头最多的堆的序号(当石头数相同时,取最左端的),然后你可以从某堆中拿走一块石头。直到石头被全部拿走。需要使得序号组成的序列字典序最小,问1到n在序列中出现的次数。

可以发现,这个序列一定是非递增的。假设现在最多的石头堆为(x),在1到x-1中石头最多的堆为(y)。考虑贪心的过程,我们需要把x到n中,石头数大于(ay)都取到(ay),因为这样能使得序号尽可能快地减小。离散化石头数,再从小到大考虑,用树状数组维护小于某个值的石头堆数量,以及石头数总和即可。

事实上,存在排序后(O(n))的做法。

Code

F - Flags 你在一条线上插(n)(flag),其中第(i)(flag)可以插在(xi)(yi)。记所有(flag)两两间的距离最小值为(d),求(d)的最大值。

暂未编写。 考虑二分答案(d)。于是是否放在(xi,yi)变成了(2-SAT)判定性问题,对于(xi)(yi)恰好放一个,距离小于(d)的位置不能同时放,构成了一些约束条件。暴力枚举所有点对,可以在(O(n^2logMAX_{x}))的时间内解决。

发现许多约束条件是无用的。考虑类似线段树的分治结构来建图,对于每个点,至多与(O(logn))个区间相连;令一方面,线段树中父子相连的边也只有(O(n))条。单次判定的复杂度可以做到(O(nlogn))。总的时间复杂度(O(nlognlogMAX_{x})),可以通过此题。

存在(O(n(logn+logMAX_x)))的算法,暂未理解。

AtCoder Regular Contest 070

D - Need 给定(n)个数(ai)。如果存在子集满足其和大于等于(K),则称为是好的子集。如果一个数(ai)所在的所有好集中,去除(ai)后仍是好集,则(ai)是无用的。求无用的数的个数。

对于(x<y),若(y)是无用的,则(x)一定无用的,所以答案满足单调性。考虑判断(x)是否是无用的,用(bitset)维护(n-1)个数相加能组成的集合((x)除外,可以用类似(DP)的方式求出)。

显然,如果其他的数能组成(K-x)(K-1)中的任意一个数,则(x)是有用的。时间复杂度(O(frac {n^2logn} w)) ,此处(w)一般为(32)(64)

Code

AtCoder Regular Contest 071

E - TrBBnsformBBtion 有字符串(S,T),仅由(A)(B)构成。有如下操作:①选择一个字符:(A ightarrow BB)(B ightarrow AA)。②删除连续3个相同的字符:(AAA)(BBB)。给定(Q)个询问,对于每个询问,回答(S[a,b])能否变换为(T[c,d])(|S|,|T|,Q leq 10^5)

想了几分钟就YY了一个结论:把A看作1,把B看作2,两个串能变换当且仅当两个区间和模3同余。然后就A掉了。首先,必要性显然,因为对于区间和模3,不论如何操作都不会改变。

看了官方题解才知道如何证明充分性。首先主要到所有的操作都是可逆的:(A ightarrow BB ightarrow AAAA ightarrow A)。且(A,B)可以任意地加3个或减3个。考虑将(S)(T)中的(B)全变为(A)。如果(S,T)(A)个个数关于3同余,则一定能变换。就证明了结论。

Code

F - Infinite Sequence 给定(n (n leq 10^6)),问存在多少个无穷序列满足:1.每个数都在1到(n)之间。2.对于任意(n leq i,j),都有(a_i=a_j)。3.对于任意的(i),若存在(i+1 leq j<k leq i+a_i),都有(a_j=a_k)

发现只有前(n)位是有用的,考虑到动态规划更容易向前转移,定义(f(i))为子序列([i,n])满足条件的个数,于是我们考虑(a_i)的值即可转移。

  • 发现1是一个比较特殊的数,当(a_i=1)时,(f(i)=f(i-1))
  • (a[i] ot=1,a[i+1] ot=1)时,序列为(ABBBBBB…)的形式,(f(i)=(n-1) imes (n-1))
  • (a[i] ot=1,a[i+1]=1)时,序列为(A,1,1,,..,1,B…)的形式,(f(i)=f(i-3)+f(i-4)+…+f(1)+n-i+2)

Code

AtCoder Regular Contest 072

D - Alice&Brown A和B在玩一个游戏。一开始,有两堆石子分别有(X)(Y)个。你可以从一堆中取(2i)个,然后放(i)个到另一堆。无法操作的玩家输。问先手是否存在必胜策略?(0 leq X,Y leq 10^{18})

通过打表发现,当(|X-Y|>=2)先手必胜,否则后手必胜。考虑如何证明。

  • 对于((X,Y)=(0,0),(0,1),(1,0),(1,1)),满足(|X-Y|<=1),是必败态。

  • 对于必胜态,设(|X-Y|=3k+r>=2 (r=0,1,-1, k>=1)) ,取(i=k),即可转移到必败态。
  • 对于必败态,操作后(X-Y)至少改变3,一定会转移到必胜态。

Code

E - Alice in linear land 给定长度为(n)的操作序列(ai)和距离(di)。对于每个(ai),当(|d-ai|<d)(|d-ai|)会成为新的(d),若最终(d=0),则称是可达的。给定(Q)个询问(qi),问能否改变(a[qi]),使得操作序列是不可达的?(n,Q leq 5 imes 10^5)

首先可以预处理前缀(a[1,qi-1])操作后的(d),记为(pre[qi-1])。发现对于询问(qi),只需要知道后缀(a[qi+1,n])使得序列不可达的最小的(d=suf[qi+1]),只要(pre[qi-1]>=suf[qi+1])就一定能做到。

于是问题转化为如何就(suf[i])。显然,(suf[n+1]=1),而且随着(i)的减小,(suf[i])一定是非递减的。当(ai>=2 imes suf[i+1]),可以取到(suf[i]=suf[i+1])(此时无法执行操作);否则(suf[i]=suf[i+1]+ai)

Code

F - Dam 有一个水坝容积为(L),一开始没有水。此后(n)天,在第(i)天早晨,会进来体积为(Vi),温度为(Ti)的水;为了下一天水不会溢出,第(i)天傍晚需要排出一些水。对于体积(V1),温度(T1)和体积(V2),温度(T2)的水混合,体积为(V1+V2),水温为(large frac {T1 imes V1+T2 imes V2}{V1+V2})。回答(n)个询问,对于第(i)个询问,输出在第(i)天能够达到的最大水温。(n leq 5 imes 10^5)

假设混合得到的水体积为(V2),温度为(T3)。由题目可知(T1 imes V1+T2 imes V2 = T3 imes V3)。考虑将((x,y)=(V,TV))抽象为一个向量,那么,水的混合就变成了向量之和!

观察这个向量,发现(T)对应的就是它的斜率!将水排出,相当于是原向量乘上<1的实数!将可能的状态画在坐标系上,可以发现这一定是一个上凸包。如图(555...图丢了,凑合脑补一下)

而新加入一个向量后,最右端的会被删除。此时不一定还是凸包,在左端比较相邻的斜率,合并即可。

整个过程用双端队列维护,复杂度(O(n))

AtCoder Regular Contest 073

Code

E - Ball Coloring(n)个包,每个包里各有两个球,权值为(xi)(yi)。你需要将一个球涂为红色,另一个球涂为蓝色。令(Rmin)为红球中的最小权值,(Rmax,Bmin,Bmax)同样定义。求出((Rmax-Rmin) imes (Bmax-Bmin))的最小值。(n leq 2 imes 10^5)

假设所有权值中的最大值为(Max),最小值(Min)。不失一般性地,有两种情况:

(Rmax=Max,Bmin=Min),此时需要最大化(Rmin),最小化(Bmax),于是将两个球中较大的涂为红色,较小的涂为蓝色。

(Rmax=Max,Rmin=Min)(Min和Max不在同一包里),此时需要最小化(Bmax),最大化(Bmin),令(xi leq yi),之后按照(x)升序排序。我们说,最优方案一定是,排序后,前(k (1 leq k leq n))个的(xi)涂为红色,后(n-k)个涂为蓝色。如何证明,考虑反证法。

假设第(p(p>=k+2))涂为了红色,那么(Bmin)并不会增大,而(Bmax)并不会减小,所以一定不会是更优解。于是简单证明了结论。

Code

F - Many Moves 在一根长度为(n)的数轴上,有两个方块,位置为(A,B)。并且在同一时刻,你能移动一块方块一个单位距离。你需要依次到达位置(xi),求最少所需时间。(n,Q leq 2 imes 10^5)

(xi)作为阶段,注意到上次的一个方块位置一定是在(x[i-1]),于是不难想到(O(n^2))的DP。(f[i,j])表示到位置(xi),另一个位置为(j)的最小时间。若原来位置为(x[i-1])的到位置(xi),即有(f[i,j]=f[i-1,j]+|x[i]-x[i-1]|)。否则即有(f[i,x[i-1]]=f[i,j]+|j-x[i-1]|)

考虑如何从优化转移的时间。对于前面的状态转移方程,事实上就是线段树的区间加。对于后面的状态转移方程,考虑维护(f[i,j]-j)(f[i,j]+j)的值,在([1,x[i-1]])(f[i,j]-j)的最值;在([x[i-1],n])(f[i,j]+j)的最值即可。阶段间的转移优化到了(O(logn))

Code

AtCoder Regular Contest 074

D - 3N Numbers 给定(3n)个数(A),你需要删除其中的(n)个数,使得剩下(2n)个数(A‘)中前(n)个数之和-后n个数之和之差最大。求最大值。(n leq 10^5)

发现对于删除后(A‘)的第(n)个数一定是在原来(A)([n,2n]),考虑暴力枚举(A‘[n])的取值,剩下的贪心地选取。整个过程用堆维护。

Code

E - RGB Sequence 您需要构造一个长度为(n), 由R,G,B构成的序列,满足以下(m)个限制。对于限制(i),满足([li,ri])间不同的颜色种数恰好为(xi)。求满足条件的序列数。(n,m leq 300)

考虑到如果存在不满足的情况,一定是DP过程中最后的R,G,B发生冲突。于是考虑状态(f[R][G][B])表示(R,G,B)最后的位置,发现当前位置(p=max{R,G,B})。考虑暴力转移,转以后判断是否冲突即可。

Code

AtCoder Regular Contest 075

D - Widespread(n)只怪兽,第(i)只怪兽初始血量(hi)。每次可以选定一只怪兽攻击,造成(A)点血量的伤害。同时其他怪兽受到(B)点血量的伤害。求最少的攻击次数。(n leq 100000)

考虑二分答案次数(T)。当某只怪物的血量(hi leq BT)时,不需要主动攻击。否则需要(large lceil frac {hi-BT} {A-B} ceil)次主动攻击,判断主动攻击次数之和是否不超过(T)次即可。

Code

F - Mirrored 对于一个正整数(n),记(rev(n))(n)的倒置,例如(rev(123)=321,rev(4000)=4)。给定(D),求存在多少(n)满足(rev(n)=n+D)(D leq 10^9)

以5位数为例,(overline{edcba}-overline{abcde}=9999(e-a)+990(d-b)) 考虑到如果(D)不是9的倍数,一定无解,否则我们考虑现将(D)除以9。然后DFS,发现((e-a) mod 10)可以确定,同样可以逐位确定剩余的位,最后乘法原理确定总方案数即可。注意奇偶分类。

Code

AtCoder Regular Contest 075

E - Connected? 给定(R imes C)棋盘上的(n)对点,要求这(n)对点彼此连线,保证这些线不相交。求是否存在方案满足。

考虑到,如果不是两个点都在边界上,一定存在方案。所以我们只要考虑边界点即可。考虑使用一个栈,顺时针处理所有的点(x),如果栈顶的点是(x),则出栈,否则令(x)入栈。最后只要检查栈是否为空即可。

Code

AtCoder Regular Contest 077

D - 11 给定(n)和长度为(n+1)的子序列,每个数都在([1,n]),且恰有一个数出现两次。对于(k=1,2,...,n+1),求出长度为(k)的互异子序列个数。(n leq 10^5)

首先找出相同的两个数(x)的位置(l,r),可以发现剩下的数都是等价的。对于每个(k),分类讨论计数。按照选取(x)个数,就是(C_{n-1}^k+2C_{n-1}^{k-1}+C_{n-1}^{k-2})。注意到,如果在((l,r))内没有选数,选择(l)和选择(r)会被当作同一情况,于是答案还要减去(C_{u+v}^{k-1})

E - guruguru 有一盏灯具有(1,2,...,m)种亮度。遥控板可以一次操作可以将亮度加一(为(m)时,变为(1))或跳转到固定的亮度(x)。一开始亮度为(a_1),接下来(n-1)次,你需要将亮度从(a_{i-1})调节到(a_i)。选取一个(x),使得调节的总次数最小。(n,m leq 10^5)

(f(x_0))为:当(x=x_0)时,需要调节的总次数。考虑亮度(sRightarrow t)(f(x))的贡献(假设(s<t), 其他情况同样处理)。

  • 对于(x leq s)(f(x)+=t-s)
  • 对于(s<x leq t)(f(x)+=t-x+1)
  • 对于(t<x)(f(x)+=t-s)

发现是区间操作,并且只有在最后查询。于是考虑差分,特别的,需要分为常数部分和系数部分。

F - SS 定义“双串”,由两个相同的字符串拼接而成。定义(f(S)),在双串S后追加最少字符得到的双串。给定(S0S0)(l,r)。求(f^{10^{100}}(S0S0))([l,r])内,26个字母分别出现的个数。(|S|<=2*10^5,l,r leq 10^{18})

有待更深入理解。用KMP预处理Next[],可以的到S0的最短相同前后缀T,设(f(S0S0)=STST)。通过画图发现,若(|T|)(|S|)的因数,那么S就是由一些T拼成的,(f(STST)=STTSTT)。否则,(f(STST)=STSTST)。设(g(S)g(S)=f(SS)) ,能得到(g^{i+2}(S)=g^{i+1}(S)+g^i(S))(显然,对于(i)无限大时也满足第一种情况)。考虑求出前缀的贡献,按照类似fib数列的递推方式计算即可。

以上是关于「泛做题解」曾经的 AtCoder 题解汇总的主要内容,如果未能解决你的问题,请参考以下文章

Atcoder Beginner Contest 251 D——题解

AtCoder Beginner Contest 172 题解

AtCoder Beginner Contest 115 题解

[AtCoder][ARC082]Sandglass 题解

AtCoder tokiomarine2020 题解

Atcoder 2335 Frequency 题解