不做了不做了。。剩下的不会了
好难啊。。争取一题一题填吧。。
csdn没有代码缩起来的操作。。贴出来太丑了。。要代码的就自己去牛客拿吧。
现在做了几题了: 7/10
B.Origami
通过观察可以发现,题目等价于从1开始按顺序把所有东西串起来,每个点只可以被串进来一次和出去一次,等价于很多个区间,互不相交。。判一下就好了
具体证明也不是很会。。
一开始互不相交写错了。。很久才反应过来。。但实际上有一个很好写的做法,就是可以观察到他是一个括号序列模型,用栈维护就好了
C.Continued Story
如果边权为1,就是简单的删边博弈
可以猜想
当边权不为1时,边权偶数,转移sg;边权大于1的奇数,转移sg^1
通过和论文同样的方法可以证明
然后就可以直接做了
输出方案也比较简单,做多一次dfs即可,这里不做详细说明了
D.The Easiest One
先考虑,如果给你一个x,y你怎么把答案算出来
很容易发现,−1-1−1操作只会至多做一次,然后就可以O(n)O(n)O(n)做了
但是如果只观察到这一个结论是不够的
我们要继续分析一下这个问题
从高位往低位来看
如果,对于一个位,x和y是是一样的,那么他们不作出贡献
当我们找到最后一个位i,满足xi>yix_i>y_ixi>yi,且他在最前的一个位j,满足xj<yjx_j<y_jxj<yj的前面
那么你会发现,决策就只有一种,就是把[i+1,n][i+1,n][i+1,n]全部变为0,然后进行−1-1−1操作,然后剩下就是直接匹配的就OK了
讨论一下各种情况,可以发现,答案等价于,x里面1的个数减去y里面1的个数再加上(n−i)(n-i)(n−i)
想到这里,就可以直接数位DP了,过程比较简单,这里就不详细说明了
G.Periodic Palindrome
成为了第三个不一样的AC代码,感觉很棒棒啊
首先,不难想到我们可以根据有没有出现过完整的周期来做
一开始的写法设了一个阈值,为n/2n/2n/2,>n/2>n/2>n/2按只出现一次的写,<=n/2<=n/2<=n/2的按有周期的写。但是后来发现,有可能出现www在中间,然后头尾都有∣w∣−1|w|-1∣w∣−1的长度,那么就GG了。。忘了为什么这么想。。可能是因为这样好讨论(大雾
由于过程有点复杂,所以还是对着代码讲吧。。
fix了一下,发现这个阈值是没有用的。。我们还是只讨论有没有完整周期就可以了
首先,你要跑一个EXKMPEXKMPEXKMP和manachermanachermanacher,对于EXKMP,我们只需要知道,某一位能不能拉到尾,我的代码里记为okiok_ioki,对于manachermanachermanacher,我们要记录iii作为反串的开头,也就是反过来匹配,可以匹配多远,记为fif_ifi,顺便记录一个一个串能不能到头和到尾,记为ok1iok1_iok1i和ok2iok2_iok2i
对于没有周期的,(i,j)(i,j)(i,j)合法的条件是
int t=i-u+1;
if (i<=t&&j+1>n-t+1&&ok2[j+1]&&ok1[i]) ans++;
然后可以发现,只要枚举i,j是一个区间,等同于求这个区间里面ok2=1ok_2=1ok2=1的个数,前缀和即可
这个部分的复杂度是O(n)O(n)O(n)的
然后是有周期的,我们就可以找周期来做
稍微观察可以发现,周期的情况,我们只需要枚举余数来找即可,别的都可以计算
自己画画图。。可以发现,对于每一个合法的周期长度iii,那么他的oki+1ok_{i+1}oki+1一定是truetruetrue的,那么就可以得到可能的合法的长度了
至于合法的长度,其实就是他的回文比所需长度大即可
写成代码大概是这样的(其中u是周期长度+1,t是u/2):
for (int i=u-t;i<=u-1;i++)//枚举终点哪一个东西在哪里
if (f[i]>=t) ans=ans+(n-i+1)/t;
容易发现,我们可以发现,t是递增的,并且每次加上的数最多只有两个取值,把两个取值分开算就好了
于是可以把fif_ifi排序后,就是区间和了,树状数组维护即可
这个部分的复杂度是O(nlogn)O(nlogn)O(nlogn)的
然后就可以通过此题了
如果要完整代码可以自己去牛客拿
E.Set
考虑,如果不是环的话,就是个傻逼题。。然而这个并没什么用
对于环的情况,我们和不是环一样正着做,那么就只是多了一个限制,就是我们想知道最后一个set和第一个最少要有多少个一样的
考虑二分答案,后进行DP
fif_ifi第iii个set和第1个set相同的下界,g表示上界
假设1号set是[1,m][1,m][1,m]
如果我们想要上界,那么肯定是要上一个取上界,然后这一个从x开始取
如果我们想要下界,那么肯定是下一个取下界,然后这个从1开始取
分类讨论以后不难得到转移(其中x是二分的答案):
一开始用系STLmin居然T了。。然后写了一个手写卡常才过。。
if (m-f[u-1]>=a[u]) g[u]=m;
else g[u]=(m-f[u-1])+(m-a[u]);
LL r=m-g[u-1]+m,now=x-r;
f[u]=m-_min(m,now+_min(m-a[u],r-m));
DP完之后随意判断一下就好了
H.Accel World
其实像这个类型的题,你可以设定某一个值,经过lim个加速点
如果答案经过的比lim要大,那么你就可以认定Burst!Burst!Burst!了
并且认定答案一定不会改变,就像样例1一样
为了防止炸精度,可以一开始给所有数乘上一个2lim2^{lim}2lim
然后你就可以DP了,DP的话,按照经过加速点的个数来转移感觉这个不是重点了。。
经过实验,发现,如果lim取大概59,用long long来存,你可以过大概12.5%的数据
看别人的代码,别人用的都是int128int128int128,这样lim就可以取到110左右了
然后就可以通过此题了。。
I.Hello, Hello and Hello
这题做了挺久。。分数的变化过程为45−65−85−10045-65-85-10045−65−85−100
其实一开始的100还是有点bug的。。然后又改了一点。。不知道还有没有bug。。反正已经AC了。。就不管了
这题说白了其实就是一个分类大讨论
分0的个数最多,1的个数最多,2的个数最多来讨论
我这里举一个0的个数的栗子,别的自己去讨论吧
假设个数分别为a,b,c,最后一个aaa出现的位置为lalala
这里分三个情况b+c=ab+c=ab+c=a,那么我们只需要从lalala一直取到222就可以了
如果b+c=a−1b+c=a-1b+c=a−1,那么我们通过上述取法以后,还需要吧[1,1][1,1][1,1]取走
否则,容易发现,这个取法是不行的,我们至少要有一对[2,3][2,3][2,3]凑在一起
通过计算发现,凑在一起的个数是t=(b+c−(a−1))/2t=(b+c-(a-1))/2t=(b+c−(a−1))/2
那么就从lblblb开始往前取ttt个
然后用同样方法取就可以了
要注意的点是,移的顺序,不要说两个阶段移过去不合法
比如说,对于222最多的情况,你先移了010101,后来移了一个121212就不合法了
剩下的情况就自己推导吧。。我觉得2和0的情况是差不多的,1的情况稍微复杂一点。。但是数据不是很强。。讨论地不是很好也可以AC