不做了不做了。。剩下的不会了
好难啊。。争取一题一题填吧。。
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,满足
x
i
>
y
i
x_i>y_i
xi>yi,且他在最前的一个位j,满足
x
j
<
y
j
x_j<y_j
xj<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
/
2
n/2
n/2,
>
n
/
2
>n/2
>n/2按只出现一次的写,
<
=
n
/
2
<=n/2
<=n/2的按有周期的写。但是后来发现,有可能出现
w
w
w在中间,然后头尾都有
∣
w
∣
−
1
|w|-1
∣w∣−1的长度,那么就GG了。。忘了为什么这么想。。可能是因为这样好讨论(大雾
由于过程有点复杂,所以还是对着代码讲吧。。
fix了一下,发现这个阈值是没有用的。。我们还是只讨论有没有完整周期就可以了
首先,你要跑一个
E
X
K
M
P
EXKMP
EXKMP和
m
a
n
a
c
h
e
r
manacher
manacher,对于EXKMP,我们只需要知道,某一位能不能拉到尾,我的代码里记为
o
k
i
ok_i
oki,对于
m
a
n
a
c
h
e
r
manacher
manacher,我们要记录
i
i
i作为反串的开头,也就是反过来匹配,可以匹配多远,记为
f
i
f_i
fi,顺便记录一个一个串能不能到头和到尾,记为
o
k
1
i
ok1_i
ok1i和
o
k
2
i
ok2_i
ok2i
对于没有周期的,
(
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是一个区间,等同于求这个区间里面
o
k
2
=
1
ok_2=1
ok2=1的个数,前缀和即可
这个部分的复杂度是
O
(
n
)
O(n)
O(n)的
然后是有周期的,我们就可以找周期来做
稍微观察可以发现,周期的情况,我们只需要枚举余数来找即可,别的都可以计算
自己画画图。。可以发现,对于每一个合法的周期长度
i
i
i,那么他的
o
k
i
+
1
ok_{i+1}
oki+1一定是
t
r
u
e
true
true的,那么就可以得到可能的合法的长度了
至于合法的长度,其实就是他的回文比所需长度大即可
写成代码大概是这样的(其中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是递增的,并且每次加上的数最多只有两个取值,把两个取值分开算就好了
于是可以把
f
i
f_i
fi排序后,就是区间和了,树状数组维护即可
这个部分的复杂度是
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)的
然后就可以通过此题了
如果要完整代码可以自己去牛客拿
E.Set
考虑,如果不是环的话,就是个傻逼题。。然而这个并没什么用
对于环的情况,我们和不是环一样正着做,那么就只是多了一个限制,就是我们想知道最后一个set和第一个最少要有多少个一样的
考虑二分答案,后进行DP
f
i
f_i
fi第
i
i
i个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要大,那么你就可以认定
B
u
r
s
t
!
Burst!
Burst!了
并且认定答案一定不会改变,就像样例1一样
为了防止炸精度,可以一开始给所有数乘上一个
2
l
i
m
2^{lim}
2lim
然后你就可以DP了,DP的话,按照经过加速点的个数来转移感觉这个不是重点了。。
经过实验,发现,如果lim取大概59,用long long来存,你可以过大概12.5%的数据
看别人的代码,别人用的都是
i
n
t
128
int128
int128,这样lim就可以取到110左右了
然后就可以通过此题了。。
I.Hello, Hello and Hello
这题做了挺久。。分数的变化过程为
45
−
65
−
85
−
100
45-65-85-100
45−65−85−100
其实一开始的100还是有点bug的。。然后又改了一点。。不知道还有没有bug。。反正已经AC了。。就不管了
这题说白了其实就是一个分类大讨论
分0的个数最多,1的个数最多,2的个数最多来讨论
我这里举一个0的个数的栗子,别的自己去讨论吧
假设个数分别为a,b,c,最后一个
a
a
a出现的位置为
l
a
la
la
这里分三个情况
b
+
c
=
a
b+c=a
b+c=a,那么我们只需要从
l
a
la
la一直取到
2
2
2就可以了
如果
b
+
c
=
a
−
1
b+c=a-1
b+c=a−1,那么我们通过上述取法以后,还需要吧
[
1
,
1
]
[1,1]
[1,1]取走
否则,容易发现,这个取法是不行的,我们至少要有一对
[
2
,
3
]
[2,3]
[2,3]凑在一起
通过计算发现,凑在一起的个数是
t
=
(
b
+
c
−
(
a
−
1
)
)
/
2
t=(b+c-(a-1))/2
t=(b+c−(a−1))/2
那么就从
l
b
lb
lb开始往前取
t
t
t个
然后用同样方法取就可以了
要注意的点是,移的顺序,不要说两个阶段移过去不合法
比如说,对于
2
2
2最多的情况,你先移了
01
01
01,后来移了一个
12
12
12就不合法了
剩下的情况就自己推导吧。。我觉得2和0的情况是差不多的,1的情况稍微复杂一点。。但是数据不是很强。。讨论地不是很好也可以AC