给定一个 n n n 个点的无根树(保证 n n n 为奇数 ),第 i i i 条边有边权 w i , 1 w_{i,1} w i , 1 。
你可以进行任意次操作,每次操作选定一条边,并将与这条边相接的所有边的 w j , 1 w_{j,1} w j , 1 异或上这条边的 w i , 1 w_{i,1} w i , 1 。你需要将所有边的 w i , 1 w_{i,1} w i , 1 变为 w i , 2 w_{i,2} w i , 2 ,求是否可以做到。
1 ≤ n ≤ 10 5 , 0 ≤ w i , 1 , w i , 2 < 2 30 1\leq n\leq 10^5,0\leq w_{i,1},w_{i,2} < 2^{30} 1 ≤ n ≤ 1 0 5 , 0 ≤ w i , 1 , w i , 2 < 2 30 。
非常深刻的一道题。
首先边权是较难处理的,我们考虑将边权转化为点权。具体地,一种较好的方法是钦定一个点 1 1 1 为根,然后点 u u u 的权 W u W_u W u 是路径 ( 1 , u ) (1,u) ( 1 , u ) 上所有边的 w i , 1 w_{i,1} w i , 1 的异或和。然后尝试刻画题意中的操作。
考虑原树的一部分:
我们选定 ( a , b ) (a,b) ( a , b ) 进行操作,会得到:
那么如果我们用 W ′ W' W ′ 表示新的点权,那么 W a ′ = W f ⊗ F ⊗ x = W b , W b ′ = W f ⊗ F ⊗ x ⊗ x = W a W'_a=W_f\otimes F\otimes x = W_b,W'_b=W_f\otimes F\otimes x\otimes x=W_a W a ′ = W f ⊗ F ⊗ x = W b , W b ′ = W f ⊗ F ⊗ x ⊗ x = W a ,而 W c , W d W_c,W_d W c , W d 因为异或两次 x x x ,所以不会变化。因此我们得到原题中选定边 ( u , v ) (u,v) ( u , v ) 进行操作,等价于交换 W u , W v W_u,W_v W u , W v 。
真的是这样吗?事实上如果我们选择了一端点是根的边,由于根没有父节点,因此会出问题。所以我们建立一个虚拟节点 E E E ,向 1 1 1 连一条边,我们不对这条边进行操作,用于保持性质。
那么我们需要调整这个 ( E , 1 ) (E,1) ( E , 1 ) 间的边权,使得每个点的点权经过交换(重排)后等于 W i , 2 W_{i,2} W i , 2 时候的点权,再额外异或上 n n n 次 ( E , 1 ) (E,1) ( E , 1 ) 的权 ω \omega ω (因为在期望时候的点权中,1 1 1 的点权为 0 0 0 ,但这不一定成立,所以需要用异或补足)。
我们可以用两个序列的异或和来(暂时)判定相等。具体地,W i , 2 W_{i,2} W i , 2 的异或和以及每个点的点权异或和我们都清楚,异或上 n n n 次 ω \omega ω 等价于异或上一次,所以我们可以求出原始点权和期望点权,它们的异或和就是 ω \omega ω 。
不过注意这样的 ω \omega ω 只是保证异或和相等,不能保证所有元素相等,所以最后用这个 ω \omega ω 去判定是否合法(点权序列是否真的相等)即可。
时间复杂度 O ( n log n ) O(n\log n) O ( n log n ) ,Submission 。
T T T 组数据。每组数据给出一个 01 01 01 字符串 S S S ,你可以进行任意次操作:
选择一个区间 [ l , r ] [l,r] [ l , r ] ,要求 S [ l , r ] S[l,r] S [ l , r ] 中 0 \texttt{0} 0 的数量与 1 \texttt{1} 1 的数量相等。 将 S [ l , r ] S[l,r] S [ l , r ] Flip(即 0 \texttt{0} 0 变成 1 \texttt{1} 1 ,1 \texttt{1} 1 变成 0 \texttt{0} 0 )。 将 S [ l , r ] S[l,r] S [ l , r ] Reverse(即翻转)。 你需要使得最后的 S S S 的字典序最小,输出这个 S S S 。
1 ≤ ∑ ∣ S ∣ ≤ 5 × 10 5 1\leq \sum |S|\leq 5\times 10^5 1 ≤ ∑ ∣ S ∣ ≤ 5 × 1 0 5 。
啊这道题真是有种如拨云雾而(直)见(接)青(升)天之感。
让我穿透云雾,直接升天 对于“0 \texttt{0} 0 的数量等于 1 \texttt{1} 1 的数量”这种限制,一种经典的处理方法是折线图模型,也就是将 0 \texttt{0} 0 看成 − 1 -1 − 1 ,1 \texttt{1} 1 看成 + 1 +1 + 1 ,则我们将 S S S 转换成了一个 ± 1 \pm 1 ± 1 序列,则 S [ l , r ] S[l,r] S [ l , r ] 中 0 \texttt{0} 0 的数量等于 1 \texttt{1} 1 的数量等价于 [ l , r ] [l,r] [ l , r ] 的和为 0 0 0 ,即 P r = P l − 1 P_r=P_{l-1} P r = P l − 1 ,其中 P P P 是这个序列的前缀和,下面我们的研究都在 P P P 上进行。
考虑这个操作在前缀和序列上干了什么,不妨假定在整个字符串 S [ 1 , ∣ S ∣ ] S[1,|S|] S [ 1 , ∣ S ∣ ] 上操作,那么研究序列 P P P 的变化:
Flip:即 P i ← − P i P_i\gets -P_i P i ← − P i 。 Reverse:由于 P n = 0 P_n=0 P n = 0 ,所以 P i ← P n − P n − i = − P n − i P_i\gets P_n - P_{n-i} = -P_{n-i} P i ← P n − P n − i = − P n − i 。 所以一次操作等价于 P i ← P n − i P_i\gets P_{n-i} P i ← P n − i ,换句话说就是将 [ 1 , ∣ S ∣ − 1 ] [1, |S|-1] [ 1 , ∣ S ∣ − 1 ] 翻转。迁移到区间 [ l , r ] [l,r] [ l , r ] 的操作就是将序列 [ l , r − 1 ] [l,r-1] [ l , r − 1 ] 翻转。
最后我们要求 S S S 的字典序最小,也就是 ± 1 \pm1 ± 1 序列字典序最小,或者说是 P P P 序列字典序最小。
我们尝试将关系建图,具体地,对于每一个 i i i ,连边 ( P i , P i + 1 ) (P_i, P_{i+1}) ( P i , P i + 1 ) ,那么我们会得到一张有向图(并且有很多重边)。
考虑如果我们将一个区间 [ l , r − 1 ] [l,r-1] [ l , r − 1 ] 翻转,在原图上会有怎样的影响,那么可以注意到我们是在将一个环上的所有边反向,但是注意到由于每条边只能将 P P P 序列 ± 1 \pm1 ± 1 ,所以如果有一个 + 1 +1 + 1 边,那么就会有一个 − 1 -1 − 1 边,所以实际上反向不会对原图产生实质上的影响。
这个图是容易构建的,现在的问题是如何通过这张图构造最优方案。我们有引理:
引理:通过任意次操作得到的一个字符串,可以与图上的一个欧拉路径一一对应。
理解起来也并不困难,首先原串本身对应了欧拉路径,可以考虑每一个欧拉路径和原串路径做对比,如果在一个位置脱离了,那么最后还要在走回这条边的,相当于我们逆向走了一个环,也就是对一个区间进行了 Flip & Reverse 操作。
所以最后我们只需要求出这张图的字典序最小的欧拉路径即可,可以用 Hierholzer 算法完成。时间复杂度 O ( ∑ ∣ S ∣ ) O(\sum |S|) O ( ∑ ∣ S ∣ ) ,Submission 。
有一个长度为 n n n 的序列 a a a ,保证 0 ≤ a i ≤ 2 0\leq a_i\leq 2 0 ≤ a i ≤ 2 ,有 q q q 次操作,支持:
1 l r
:∀ i ∈ [ l , r ] , a i ← ( a i + 1 ) m o d 3 \forall i\in[l, r], a_i\gets (a_i+1)\bmod 3 ∀ i ∈ [ l , r ] , a i ← ( a i + 1 ) mod 3 。2 l r
:令 T = a [ l , r ] T=a[l, r] T = a [ l , r ] ,你在序列 T T T 上玩一个游戏,每次选择相邻两个相等的数并将它们删除,重复上述操作直至无法操作为止,询问你是否可以将 T T T 变成空序列。1 ≤ n , q ≤ 5 × 10 5 1\leq n,q\leq 5\times 10^5 1 ≤ n , q ≤ 5 × 1 0 5 。
每天一个神奇 trick。
假如我们找到了一个非 Abel 群 G G G ,并适当选择其中三个元素 k 0 , k 1 , k 2 ∈ G k_0,k_1,k_2\in G k 0 , k 1 , k 2 ∈ G ,那么在序列的奇数位放 a k i a_{k_i} a k i ,偶数位放 a k i − 1 a_{k_i}^{-1} a k i − 1 ,那么在查询时,如果区间 [ l , r ] [l,r] [ l , r ] 的乘积为 ϵ \epsilon ϵ ,说明我们可以通过改变运算先后顺序(而不是交换顺序),使得每次运算的结果都是 ϵ \epsilon ϵ ,即区间 [ l , r ] [l,r] [ l , r ] 可以通过玩游戏变成空序列(因为在理想情况下,只有相邻相同的数,乘起来才会使 ϵ \epsilon ϵ )。
这样的群是非常常见的,典型代表就是矩阵乘法。因此我们可以寻找三个可逆形状相同的可逆方阵,然后用线段树维护区间乘积,查询时判断乘积是否为单位矩阵 I I I 即可,修改的话可以改为每个节点存储一个长度为 3 3 3 的矩阵列,分别表示序列中这一位(模 3 3 3 意义下) + 0 , + 1 , + 2 +0,+1,+2 + 0 , + 1 , + 2 后的新矩阵,那么修改就变成了对这个东西做一次循环移位,也是容易叠加的。
有一个小技巧,如何选择这样的矩阵?为了方便,可以直接用 2 × 2 2\times 2 2 × 2 的。为了更方便些,我们可以采用对合矩阵 ,即逆矩阵为本身的可逆矩阵(这样就不需要按照奇偶分类讨论了)。构造对合矩阵可以用对合矩阵通式:
A = [ a b c − a ] ( a 2 + b c = 1 ) A=\begin{bmatrix} a& b\\ c& -a \end{bmatrix}\quad (a^2+bc=1) A = [ a c b − a ] ( a 2 + b c = 1 )
时间复杂度 O ( q log n ) O(q\log n) O ( q log n ) ,Submission 。
每日一道 JOISC (1 / 1)。
这是一道交互题 。
有 2 n 2n 2 n 只变色龙,其中 n n n 只是雄性,n n n 只是雌性。具体地,若 Y i = 0 Y_i=0 Y i = 0 表示变色龙 i i i 是雌性,否则是雄性。
第 i i i 只变色龙的原本颜色是 C i C_i C i ,且喜欢变色龙 L i L_i L i ,C i , L i C_i,L_i C i , L i 满足:
Y i ≠ Y L i , C i ≠ C L i Y_i\neq Y_{L_i}, C_i\neq C_{L_i} Y i = Y L i , C i = C L i ,即变色龙只会喜欢和自己颜色不同的异性。∀ i ≠ j , L i ≠ L j \forall i\neq j, L_i\neq L_j ∀ i = j , L i = L j ,即不存在两只变色龙喜欢同一只变色龙。∀ ( i ≠ j , Y i = Y j ) , C i ≠ C j \forall (i\neq j, Y_i=Y_j), C_i\neq C_j ∀ ( i = j , Y i = Y j ) , C i = C j ,即同性变色龙颜色互异。∀ i , ∃ Y i ≠ Y j , C i = C j \forall i, \exists Y_i\neq Y_j, C_i=C_j ∀ i , ∃ Y i = Y j , C i = C j ,即对于每一只变色龙,都存在一只与其颜色相同的异性变色龙。你只知道 n n n 和关于 L , C , Y L,C,Y L , C , Y 的这些限制。但你不知道 L , C , Y L,C,Y L , C , Y 的具体值。所幸你可以进行最多 2 × 10 4 2\times 10^4 2 × 1 0 4 次询问 int Query(const vector<int>& p)
,表示组织向量 p p p 中的所有变色龙开会。若变色龙 i i i 参加会议,且 L i L_i L i 也参加会议,变色龙 i i i 就会将自己的颜色变成 C L i C_{L_i} C L i (不会修改 L i L_i L i ),该函数会返回与会的所有变色龙的颜色数量。
你需要实现函数 void Solve(int n)
,通过若干次询问求出每一对同色的异性变色龙,调用 n n n 次 void Answer(int a, int b)
来报告你求出的答案。
对于 40 % 40\% 40% 的测试点,n ≤ 50 n\leq 50 n ≤ 50 。对于 100 % 100\% 100% 的测试点,1 ≤ n ≤ 500 1\leq n\leq 500 1 ≤ n ≤ 500 。
非常神奇的交互题,使我大脑旋转。
先来考虑 40 40 40 分应该怎么做,为了获取尽可能多的有用信息,不妨获取所有 Query({i, j})
的答案,记作 Q ( i , j ) Q(i,j) Q ( i , j ) 。那么容易发现 Q ( i , j ) ∈ { 1 , 2 } Q(i,j)\in \{1, 2\} Q ( i , j ) ∈ { 1 , 2 } 。
若 Q ( i , j ) = 1 Q(i,j)=1 Q ( i , j ) = 1 ,可以发现 i , j i,j i , j 只能是如下关系之一:
C i = C j C_i=C_j C i = C j ,即 i , j i,j i , j 是同色的异性变色龙。L i = j , L j ≠ i L_i=j,L_j\neq i L i = j , L j = i ,即变色龙 i i i 喜欢变色龙 j j j ,但 j j j 不喜欢 i i i 。L j = i , L i ≠ j L_j=i,L_i\neq j L j = i , L i = j ,即变色龙 j j j 喜欢变色龙 i i i ,但 i i i 不喜欢 j j j 。我们发现变色龙之间的“同色”是一种双向关系,但是“喜欢”是一种单向关系。无论如何它们都是二元关系,因此可以考虑建图。对于 C i = C j C_i=C_j C i = C j ,我们连一条黑色无向边 ( i , j ) (i,j) ( i , j ) ,对于 L i = j L_i=j L i = j ,我们连一条绿色有向边 ( i , j ) (i,j) ( i , j ) 。那么我们就得到了一张混合图,例如:
如果将每条边都视为无向边,那么我们得到的其实是一张二分图(因为同色的两个变色龙是异性,变色龙也只会喜欢异性变色龙,所以性别就可以看成一组染色)。不妨将两条绿色的蓝边去除,这样子我们就得到了一张简单图,这样的好处是 Q ( i , j ) = 1 Q(i,j)=1 Q ( i , j ) = 1 表明存在边 ( i , j ) (i,j) ( i , j ) :
对于 40 40 40 分的数据,我们可以 O ( n 2 ) O(n^2) O ( n 2 ) 暴力询问出所有 Q ( i , j ) Q(i,j) Q ( i , j ) ,然后建出这张图,现在只需要关注如何通过这张图来求得答案。
考察每个点的度数,在原图上,每个点的度数应该都是 3 3 3 ,但是在新图上则出现了度数为 1 1 1 的点,它是双向喜欢关系引起的,我们暂时忽略这些点。对于一个度数为 3 3 3 的点 i i i ,我们可以找出它的邻域 { x , y , z } \{x,y,z\} { x , y , z } ,那么 x , y , z x,y,z x , y , z 中一定有一只变色龙与 i i i 同色,其余的是与 i i i 间有喜欢 / 被喜欢关系的变色龙。
考虑如何找到那只与 i i i 同色的变色龙,我们可以尝试挑出两只变色龙 x , y x,y x , y 与 i i i 一起组织会议,那么实际上有三种情况:
C x = C i , L y = i C_x=C_i,L_y=i C x = C i , L y = i ,即 x x x 与 i i i 同色,y y y 喜欢 i i i 。此时组织会议 y y y 的颜色会变成 C i C_i C i ,x , i x,i x , i 不变,因此询问结果为 1 1 1 。C x = C i , L i = y C_x=C_i,L_i=y C x = C i , L i = y ,即 x x x 与 i i i 同色,i i i 喜欢 y y y 。此时组织会议 i i i 的颜色会变成 C y C_y C y ,y , i y,i y , i 不变,因此询问结果为 2 2 2 。L x = i , y = L i L_x=i,y=L_i L x = i , y = L i ,即 x x x 喜欢 i i i ,i i i 喜欢 y y y 。此时组织会议 x x x 的颜色会变成 C i C_i C i ,i i i 的颜色会变成 C y C_y C y ,y y y 不变。因此询问结果为 2 2 2 。那么我们可以通过两次询问中找到一组询问结果为 1 1 1 的 x , y x,y x , y ,此时我们至少可以确定 L i = z L_i=z L i = z ,即在原图 / 新图中存在边 ( i , z ) (i,z) ( i , z ) ,并且可以发现所有绿色边都可以通过这种方法找到,那么剩下的边自然也就是黑色边了。这一部分只需要 ∼ 2 n \sim 2n ∼ 2 n 次询问,代码片段如下:
for ( int i = 1 ;i <= (n << 1 );i ++ ){
int ngb [ 3 ], t = 0 ;
for ( int j = 1 ;j <= (n << 1 );j ++ ) if ( g [i][j]) ngb [t ++ ] = j;
if (t == 1 ) continue ;
auto query = [ & ]( int x , int y , int z ){
if ( Query ({i, x, y}) == 1 ) return g [i][z] = g [z][i] = 2 , 0 ;
return 1 ;
};
auto [x, y, z] = ngb;
if ( query (x, y, z)) if ( query (x, z, y)) g [i][x] = g [x][i] = 2 ;
}
for ( int i = 1 ;i <= (n << 1 );i ++ ){
for ( int j = 1 ;j < i;j ++ ) if ( g [i][j] == 1 ) Answer (i, j);
}
我们发现要想拿到 100 100 100 分,关键在于优化建图的过程(因为通过图来求答案不是瓶颈)。
这里就比较需要人类智慧了,我们考察新图的一个独立集,比如 { 1 , 3 , 6 , 7 } \{1,3,6,7\} { 1 , 3 , 6 , 7 } ,那么如果让这些变色龙一起开会,答案肯定就是独立集的大小,但是这个条件并不充要(比如这些可怜的变色龙构成了三角恋或者四角恋之类的)。不过如果采用增量法,这就是显然成立的:
引理:对于新图的一个独立集 I I I ,对于 u ∉ I u\not\in I u ∈ I ,I ∪ { u } I\cup \{u\} I ∪ { u } 也是独立集当且仅当 I ∪ { u } I\cup\{u\} I ∪ { u } 这些变色龙组织会议时,答案恰好为 ∣ I ∣ + 1 |I|+1 ∣ I ∣ + 1 。
那么可以通过 n n n 次询问找出新图的一个独立集:增量法维护当前独立集 I I I ,对于尝试加入的点 u u u ,若 I ∪ { u } I\cup\{u\} I ∪ { u } 的答案是 ∣ I ∣ + 1 |I|+1 ∣ I ∣ + 1 ,就将 u u u 加入到 I I I 中。
由于每个点的度数最多为 3 3 3 ,因此加入一个点最多排除之后的三个点,因此这个独立集的大小至少为 n 4 \frac{n}{4} 4 n 。
独立集中肯定是没有边的,因此我们实际上给规模乘上了 3 4 \frac{3}{4} 4 3 ,不过还需要处理一下其他点连向独立集的边。
考虑枚举 I ‾ \overline{I} I 中的每个点 u u u ,考察 u , I u,I u , I 之间有哪些边。注意到判定独立集 I I I 的非空子集一定也是独立集,且判断独立集 I ′ I' I ′ 与 u u u 间有没有边,等价于判断 I ′ ∪ { u } I'\cup \{u\} I ′ ∪ { u } 是否是独立集,因此可以进行若干次二分来找到所有与 u u u 相连的独立集上的点,因此也就确定了这些边。
于是我们成功将规模为 n n n 的问题,以 O ( n log n ) O(n\log n) O ( n log n ) 的询问次数,O ( n 2 log n ) O(n^2\log n) O ( n 2 log n ) 的时间复杂度归约到了一个规模为 3 4 n \frac{3}{4}n 4 3 n 的问题。因此我们可以删去独立集,重复上述操作直至点集为空。这样就询问出了新图的所有边。
分析一下总询问次数和时间复杂度。对于总询问次数,有 T ( n ) = T ( 3 4 n ) + O ( n log n ) = O ( n log n ) T(n)=T(\frac{3}{4}n)+O(n\log n)=O(n\log n) T ( n ) = T ( 4 3 n ) + O ( n log n ) = O ( n log n ) ,对于时间复杂度有 T ( n ) = T ( 3 4 n ) + O ( n 2 log n ) = O ( n 2 log n ) T(n)=T(\frac{3}{4} n)+O(n^2\log n)=O(n^2\log n) T ( n ) = T ( 4 3 n ) + O ( n 2 log n ) = O ( n 2 log n ) ,这大致是可以接受的(我的实现中,实测最大询问次数为 18866 18866 18866 刚好可以通过),Submission 。
每日一道 JOISC (1 / 1)。
有一辆长途汽车在时刻 0 0 0 从起点出发,在时刻 X X X 到达终点,沿途经过 n n n 个服务区,在时刻 S i S_i S i 到达服务区 i i i 。
汽车上有一个容量无限的水箱,在发车前水箱是空的。你可以在起点或服务区给水箱瞬间加水,但是加一升水需要 W W W 元。本汽车有 m m m 位乘客和一位司机。给定 T T T ,乘客 i i i 会在每个时刻 k T + D i ( k ∈ N ) kT+D_i\ (k\in\mathbb{N}) k T + D i ( k ∈ N ) 需要接一升水,司机会在每个时刻 k T ( k ∈ N ) kT\ (k\in\mathbb{N}) k T ( k ∈ N ) 需要接一升水。
如果乘客 i i i 在某个时刻没有接到水,那么他就会怒而下车,此时需要支付 C i C_i C i 元赔偿。如果司机在某个时刻没有接到水,那么车就会抛锚,这是禁止的。你需要求出最少要花费多少元(包括水费和赔偿金)。
保证一个时刻最多只会有最多一个人需要接水,保证在时刻 X X X 或到达服务区时,没有人需要接水。
1 ≤ T ≤ X ≤ 10 12 , 1 ≤ n , m ≤ 2 × 10 5 , 1 ≤ W ≤ 10 6 , 1 ≤ C i ≤ 10 9 1\leq T\leq X\leq 10^{12},1\leq n,m\leq 2\times 10^5,1\leq W\leq 10^6,1\leq C_i\leq 10^9 1 ≤ T ≤ X ≤ 1 0 12 , 1 ≤ n , m ≤ 2 × 1 0 5 , 1 ≤ W ≤ 1 0 6 , 1 ≤ C i ≤ 1 0 9 。
首先你发现并没有很直观的多项式级别的做法,这让你意识到了问题的严重性。
引理 :如果在一段 ( S i , S i + 1 ) (S_i,S_{i+1}) ( S i , S i + 1 ) 中需要赶人下车,那么如果将每个乘客按照 D i D_i D i 排序,那么一定是赶走一段连续区间的乘客,并且赶人的时机是在到达 S i + 1 S_{i+1} S i + 1 的最后一个周期。
如何理解这一引理?首先如果在一段中 ( S i , S i + 1 ) (S_i,S_{i+1}) ( S i , S i + 1 ) 需要赶两个无交的不连续区间 [ l 1 , r 1 ] , [ l 2 , r 2 ] [l_1,r_1],[l_2,r_2] [ l 1 , r 1 ] , [ l 2 , r 2 ] 的乘客下车,那么乘客 r 1 r_1 r 1 一定没有接到水,那么介于区间 [ r 1 + 1 , l 2 − 1 ] [r_1+1,l_2-1] [ r 1 + 1 , l 2 − 1 ] 的乘客一定也没有接到水,也会下车,所以实际上赶走了 [ l 1 , r 2 ] [l_1,r_2] [ l 1 , r 2 ] 的乘客,是一段连续的区间。如果考虑在中间的一个周期赶人而不是最后一个周期赶人,那么司机一定也没有接到水,而这是禁止的。所以一定是在最后一个周期赶人。
于是可以枚举每一段赶走了多少人来做到 O ( m n ) O(m^n) O ( m n ) ,显然是不可行的。
考虑换一个想法,改为决策每个乘客是否要赶走,结合前面连续区间的结论,很容易想到 dp,设 f i f_i f i 表示按照 D i D_i D i 排序的前 i i i 个乘客,最少需要花费多少元在他们身上。
如何转移?可以发现有两种转移。一种转移是不赶走他,那么就需要结清所有他接的水的水费:
f i ← f i − 1 + W ⋅ ( ⌊ X − D i T ⌋ + 1 ) f_i\gets f_{i-1}+W\cdot \left(\left\lfloor \frac{X - D_i}{T} \right\rfloor + 1\right) f i ← f i − 1 + W ⋅ ( ⌊ T X − D i ⌋ + 1 )
另一种转移是赶走他,我们不妨钦定这是被赶走的一段乘客区间的结尾。那么可以得到:
f i ← min k = 0 i − 1 f k + ∑ t = k + 1 i C t + W t i f_i\gets\min_{k=0}^{i-1} f_k+\sum_{t=k+1}^{i} C_t + Wt_i f i ← k = 0 min i − 1 f k + t = k + 1 ∑ i C t + W t i
也就是枚举赶走的一段区间,先支付赔偿金 C t C_t C t ,然后支付下车前的水费 W t i Wt_i W t i ,t i t_i t i 表示乘客 i i i 被赶走时,他最少需要接多少水。由于赶走一定是在一段的末尾,那么可以看成每一段的右端点找一个前驱,这可以二分查找,O ( n log m ) O(n\log m) O ( n log m ) 完成。
不妨记录 P i = ∑ k = 1 i C k P_i=\sum_{k=1}^{i} C_k P i = ∑ k = 1 i C k ,那么转移可以写成:
f i = min ( f i − 1 + W ⋅ ( ⌊ X − D i T ⌋ + 1 ) , min k = 0 i − 1 f k + P i − P k + W t i ( i − k ) ) f_i=\min\left(f_{i-1}+W\cdot \left(\left\lfloor \frac{X - D_i}{T} \right\rfloor + 1\right), \min_{k=0}^{i-1} f_k+P_i-P_k+Wt_i(i-k)\right) f i = min ( f i − 1 + W ⋅ ( ⌊ T X − D i ⌋ + 1 ) , k = 0 min i − 1 f k + P i − P k + W t i ( i − k ) )
最后记得加上司机的水费,直接转移时间复杂度为 O ( m 2 ) O(m^2) O ( m 2 ) ,可以获得 71 71 71 分,Submission 。
优化,第一种转移可以单次 O ( 1 ) O(1) O ( 1 ) 完成,关键在第二种询问,尝试改写一下式子:
f i ← f k + P i − P k + W t i ( i − k ) f i − P i − W t i i ← − W k t i + ( f k − P k ) \begin{aligned} &f_i\gets f_k+P_i-P_k+Wt_i(i-k)\\ &f_i-P_i-Wt_i i\gets -Wk t_i + (f_k-P_k) \end{aligned} f i ← f k + P i − P k + W t i ( i − k ) f i − P i − W t i i ← − Wk t i + ( f k − P k )
可以看成动态插入一次函数,查询一次函数在 x = t i x=t_i x = t i 时的最小值,李超线段树即可。时间复杂度 O ( n log m + m log V ) O(n\log m+m\log V) O ( n log m + m log V ) 可以通过本题,Submission 。
给定一个长度为 n n n 的序列 a a a ,有 q q q 次操作,支持:
1 l r v
:∀ a i ∈ [ l , r ] , a i ← ⌊ a i v ⌋ \forall a_i\in [l, r], a_i\gets \left\lfloor \frac{a_i}{v} \right\rfloor ∀ a i ∈ [ l , r ] , a i ← ⌊ v a i ⌋ ,保证 v i ≥ 1 v_i\geq 1 v i ≥ 1 。2 l r v
:∀ a i ∈ [ l , r ] a i ← a i & v \forall a_i\in[l, r] a_i\gets a_i\& v ∀ a i ∈ [ l , r ] a i ← a i & v ,其中 & \& & 表示按位与运算。3 l r
:计算 ∑ k = l r a k ( m o d 2 128 ) \sum\limits_{k=l}^{r} a_k \pmod{2^{128}} k = l ∑ r a k ( mod 2 128 ) 。1 ≤ n ≤ 3 × 10 5 , 1 ≤ q ≤ 2 × 10 5 , 0 ≤ a i < 2 128 1\leq n\leq 3\times 10^5,1\leq q\leq 2\times 10^5,0\leq a_i<2^{128} 1 ≤ n ≤ 3 × 1 0 5 , 1 ≤ q ≤ 2 × 1 0 5 , 0 ≤ a i < 2 128 。时间限制 2 s 2\text{s} 2 s ,空间限制 1024 MB 1024\text{MB} 1024 MB 。
一个区间除,一个区间按位与,一个区间求和,操作确实很诡异。
对于区间除,经典方法是势能线段树,在每个节点维护一个 z e r o \mathrm{zero} zero 表示这个区间是否全为 0 0 0 ,修改节点时,如果 z e r o \mathrm{zero} zero 不成立,那么就向下递归,记得判掉 v = 1 v=1 v = 1 的情况,那么每次一个每个元素至少减半,匡爷教导我这个东西的时间复杂度其实是 O ( n log V ) O(n\log V) O ( n log V ) 的。
考虑区间与,可以拆位,对于每一位维护一下该位在区间中的出现次数,那么我们需要在每个节点维护长度为 O ( log V ) O(\log V) O ( log V ) 的值域至多为 n n n 的序列,时间复杂度 O ( q log n log V ) O(q\log n\log V) O ( q log n log V ) 不能通过。
我们发现 V V V 很大而 n n n 很小,将维护的东西转置,变成维护一个长度为 O ( log n ) O(\log n) O ( log n ) 的值域至多为 V V V 的序列,表示有哪些位的方案数有 2 i 2^i 2 i 这一位。那么 make tag 是容易的,pushup 的时候就是手动模拟加法,需要考虑进位。时间复杂度 O ( n log V + q log 2 n ) O(n\log V+q\log^2 n) O ( n log V + q log 2 n ) 。可以通过本题,Submission 。
有一个长度为 n n n 的排列 p p p ,并给定一个长度为 n ( n − 1 ) 2 \frac{n(n-1)}{2} 2 n ( n − 1 ) 的序列 A A A ,包含了所有满足 1 ≤ a < b ≤ n 1\leq a<b\leq n 1 ≤ a < b ≤ n 的二元组 ( a , b ) (a,b) ( a , b ) 。然后会进行一个游戏,第 i i i 轮时主持人会告诉你 A i = ( a , b ) A_i=(a,b) A i = ( a , b ) 中是否满足 p a < p b p_a<p_b p a < p b 。如果存在一个排列 p p p 使得你在每一轮都不能正确预知主持人的回答,那么称这个排列是好的。你需要求出有多少个好的排列,答案对 10 9 + 7 10^9+7 1 0 9 + 7 取模。
1 ≤ n ≤ 400 1\leq n\leq 400 1 ≤ n ≤ 400 。
考虑对于三元组 ( a , b , c ) (a,b,c) ( a , b , c ) ,如果 ( a , b ) (a,b) ( a , b ) 和 ( b , c ) (b,c) ( b , c ) 在 A A A 序列中排在 ( a , c ) (a,c) ( a , c ) 之前,且获悉了 p a < p b p_a<p_b p a < p b ,那么对于好的排列 p p p ,p b < p c p_b<p_c p b < p c 一定不成立(因为这样就可以推断出 p a < p c p_a<p_c p a < p c 了),所以只能有 p b > p c p_b>p_c p b > p c ,反之亦然。
考虑通过每一个二元组的答案来计算排列的数量,那么每个二元组有小于和大于两种结果,并且有形如【若 A A A 的 p p p 成立,则 B B B 的 q q q 成立】这种约束,直接套用 2-SAT 即可。
最后计数时,对于每一个强连通分量肯定只能选择同样的结果,但是由于我们给每一个二元组都拆成了两个点,所以如果有解的话,一定强连通分量可以两两一组,每一组都必须得到不同的结果。所以答案就是 2 c 2 2^{\frac{c}{2}} 2 2 c ,其中 c c c 表示强连通分量的数量。
时间复杂度 O ( n 3 ) O(n^3) O ( n 3 ) ,Submission 。
给定两个长度为 n n n 的序列 X , Y X,Y X , Y 和一个 m × n m\times n m × n 的矩阵 A A A 。你需要恰好进行 m m m 次操作,第 i i i 次操作选择下列两个操作中的一个执行:
令 ∀ k ∈ [ 1 , n ] , X k ← max ( X k , A i , k ) \forall k\in[1, n], X_k\gets \max(X_k,A_{i,k}) ∀ k ∈ [ 1 , n ] , X k ← max ( X k , A i , k ) 。 令 ∀ k ∈ [ 1 , n ] , Y k ← max ( Y k , A i , k ) \forall k\in[1, n], Y_k\gets \max(Y_k,A_{i,k}) ∀ k ∈ [ 1 , n ] , Y k ← max ( Y k , A i , k ) 。 求出最终 ∑ i = 1 n X i + Y i \sum_{i=1}^{n} X_i+Y_i ∑ i = 1 n X i + Y i 的最小值。
1 ≠ n ≤ 10 , 1 ≤ X i , Y i , A i , j , m ≤ 500 1\neq n\leq 10,1\leq X_i,Y_i,A_{i,j},m\leq 500 1 = n ≤ 10 , 1 ≤ X i , Y i , A i , j , m ≤ 500 。
首先看到题意应该可以想到不少贪心,但是这些贪心几乎都是假的。不过参考 P3227 [HNOI2013] 切糕 ,不妨想想最小割建模。
由于 X , Y , A X,Y,A X , Y , A 三者的值域都不大,因此可以考虑用切糕一题的方法将每个 X i , Y i X_i,Y_i X i , Y i 拆成一条链。具体地,我们取一个值域上界 V V V ,将 X i X_i X i 拆成 V V V 个点 U i , 1 , U i , 2 , ⋯ , U i , V U_{i, 1}, U_{i, 2}, \cdots, U_{i, V} U i , 1 , U i , 2 , ⋯ , U i , V 。然后连边 ( U i , j , U i , j + 1 , j ) , ( S , U i , 1 , + ∞ ) , ( U i , n , T , V ) (U_{i,j}, U_{i,j+1}, j), (S, U_{i,1}, +\infty), (U_{i, n}, T, V) ( U i , j , U i , j + 1 , j ) , ( S , U i , 1 , + ∞ ) , ( U i , n , T , V ) 。另外 X i X_i X i 初始时已经有了一个下界(也就是初始值),我们连边 ( S , U i , X i , + ∞ ) (S,U_{i,X_i},+\infty) ( S , U i , X i , + ∞ ) 来保证总是割断 X i X_i X i 及以后的边。
对于 Y i Y_i Y i 也是类似的,不过为了体现他们的不同,我们不妨将 Y Y Y 倒过来拆成一条链:
然后我们考虑第 k k k 次操作,枚举 i i i 考察限制 A k , i A_{k,i} A k , i 。我们新建一个点 O O O ,O O O 划分到 S S S 割集意味着我们选择 X X X ,否则选择 Y Y Y ,连边 ( O , U i , A k , i , + ∞ ) (O, U_{i, A_{k, i}}, +\infty) ( O , U i , A k , i , + ∞ ) 以及 ( V i , A k , i , O , + ∞ ) (V_{i, A_{k, i}}, O, +\infty) ( V i , A k , i , O , + ∞ ) 。前者表示当 O O O 划分到 S S S 割集时,U i , A k , i U_{i, A_{k,i}} U i , A k , i 始终在 S S S 割集,那么 X i X_i X i 就必须大于等于 A k , i A_{k,i} A k , i ;后者同理。
如何判断与 O O O 连接的两种边的方向
当 O O O 被划分到割集 S S S 时,可以将 O O O 就看成 S S S ,那么肯定是 O → U O\to U O → U 不是 U → O U\to O U → O ,V V V 同理。
根据最小割最大流定理,我们可以用最大流算法求该图的最小割。时间复杂度 O ( m a x f l o w ( V n + m , n ( V + m ) ) ) O(\mathrm{maxflow}(Vn+m, n(V+m))) O ( maxflow ( Vn + m , n ( V + m ))) 可以通过本题,Submission 。