2020牛客暑期多校训练营(第三场)
A.Clam and Fish
显然有鱼钓鱼,没鱼有饵钓鱼,没鱼没饵做饵
B.Classical String Problem
问:给定若干操作,每次把string循环右移/左移x位。问第y位是什么
取模就行。。。。一开始纯nt,写了splay,T了
C.Operation Love
有几条边长是整数,可以唯一确定左下角的坐标,然后通过叉积来判断这个向量是大于0还是小于0来判断左手还是右手。
D.Points Construction Problem
显然:一个单独点+4,一个n个点的线位2+2n。
一个NxM的矩阵为2(N+M)
当全是离散单点的时候最大,当凑满正方形矩阵时最小,这样可以得出上下界。
然后发现对于一个矩阵,只要保证行列不变无孤立点,其中随意删点后都不会影响整体的总数,一个L形和一个矩阵的贡献是一样的。
有了这若干种情况后,发现必然是2的倍数,所以不是2的倍数biss
之后就是不断-4-4-4-4-4…感觉差不多时候拼个L,然后往上叠就行了。
E.Two Matchings
就是给一列数,
下标找一个排列后相邻两个组合,如(1,2) (3,4)使两两差最小。
然后再找一个排数,还是这个问题,但是不能有一个组合和之前的下标一样
第一个排列就是排个序vans了
我们只考虑第二个问题。
我们把问题转换一下:
给定两个集合:Left和Right,你每次可以放一个数字在其中一个集合里,目标使使得两个集合的差值最小。
限制如下:
∣
L
e
f
t
∣
≥
∣
R
i
g
h
t
∣
|Left| \geq |Right|
∣Left∣≥∣Right∣
若
∣
L
e
f
t
∣
=
=
∣
R
i
g
h
t
∣
−
1
,
且
上
一
个
元
素
在
L
e
f
t
,
则
当
前
元
素
必
须
在
R
i
g
h
t
若|Left|==|Right| - 1,且上一个元素在Left,则当前元素必须在Right
若∣Left∣==∣Right∣−1,且上一个元素在Left,则当前元素必须在Right
显然DP
for(int i = 1 ; i <= n ; ++i)
for (int j = 0 ; j <= 2 ; ++j)
for (int k = 0 ; k < 2 ; ++k)
{
if(f[i][j][k] >= INF) continue;
//消去
if(j > 1){ //多余很多Left组
f[i+1][j-1][0] = min(f[i+1][j-1][0], f[i][j][k] - arr[i]);
}
if(j == 1 && k == 0) { //只有1组,但不是前面那组
f[i+1][j-1][0] = min(f[i+1][j-1][0], f[i][j][k] - arr[i]);
}
//加入
if(j + 1 <= 2)
f[i+1][j+1][1] = min(f[i+1][j+1][1],f[i][j][k] + arr[i]);
}
res += f[n+1][0][0];
F.Fraction Construction Problem
显然当
g
c
d
(
a
,
b
)
≠
1
gcd(a,b) \neq 1
gcd(a,b)=1的时候,令
g
=
g
c
d
(
a
,
b
)
g=gcd(a,b)
g=gcd(a,b)
a
/
g
+
1
b
/
g
−
1
b
/
g
=
a
/
g
b
/
g
=
a
b
\frac{a/g+1}{b/g} - \frac{1}{b/g} =\frac{a/g}{b/g} = \frac{a}{b}
b/ga/g+1−b/g1=b/ga/g=ba
对于其余情况,移动公式:
c
f
−
e
d
d
f
=
a
b
\frac{cf-ed}{df} =\frac{a}{b}
dfcf−ed=ba
因为
d
,
f
<
b
d,f < b
d,f<b,所以
d
,
f
d,f
d,f为b的因数。若
b
b
b为素数显然不行。
找到合适的
d
,
f
d,f
d,f以后,由于
g
c
d
(
a
,
b
)
=
1
gcd(a,b) = 1
gcd(a,b)=1
由扩展欧几里得可以找到这样的
c
,
e
c,e
c,e使得
c
f
−
e
d
=
1
cf-ed = 1
cf−ed=1,然后在放缩a倍即可
G.Operating on a Graph
并查集,List模拟即可
H.Sort the Strings Revision
排在前面的字符的贡献自然大于后面的字符。
对于区间
[
L
,
R
]
[L,R]
[L,R],如果我们找到了其中排在最前面
p
[
i
]
p[i]
p[i],假设是字典序变小
那么自然
[
L
,
i
]
[L,i]
[L,i]区间的排名不变,
[
i
+
1
,
R
]
[i+1,R]
[i+1,R] 区间的排名均往后拖。
字典序变大是同样的道理。
如果
d
[
i
]
d[i]
d[i]和原来一样, 那就是不处理,直接处理下一个。
怎么样才能不处理呢?
在默认情况下,从1开始递归处理直到
l
=
r
l = r
l=r, 或者是当前
p
[
i
]
=
n
p[i]=n
p[i]=n就停止
我们只要令
d
[
i
]
=
s
[
p
[
i
]
]
d[i] = s[p[i]]
d[i]=s[p[i]]的
p
[
i
]
=
n
+
1
p[i]=n+1
p[i]=n+1就可以做到。
然后当排名相同时前面的小即可。
使用笛卡尔树可以做到O(N)
笛卡尔树可以极高效率地找到,左边/右边第一个比该数大/小的位置。
而
p
数
列
p数列
p数列是一个排列的部分和n+1组成。