「泛做题解」曾经的 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,k\in Z)\)被多少个不同区间覆盖(对于不同的\(k\),只算一次)。\(1 \leq n,m \leq 3\times 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\times 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))\times 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\rightarrow BB\)\(B\rightarrow 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\rightarrow BB\rightarrow AAAA\rightarrow 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]\not=1,a[i+1]\not=1\)时,序列为\(ABBBBBB…\)的形式,\(f(i)=(n-1)\times (n-1)\)
  • \(a[i]\not=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\times 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\times 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\times V1+T2\times V2}{V1+V2}\)。回答\(n\)个询问,对于第\(i\)个询问,输出在第\(i\)天能够达到的最大水温。\(n \leq 5\times 10^5\)

假设混合得到的水体积为\(V2\),温度为\(T3\)。由题目可知\(T1\times V1+T2\times V2 = T3\times 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)\times (Bmax-Bmin)\)的最小值。\(n \leq 2\times 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\times 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}\rceil\)次主动攻击,判断主动攻击次数之和是否不超过\(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 \times 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\)时,需要调节的总次数。考虑亮度\(s\Rightarrow 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数列的递推方式计算即可。

猜你喜欢

转载自www.cnblogs.com/cyanic/p/9159463.html