Hello 2020 
B. New Year and Ascent Sequence  
这题实际上是一个计数问题,要求任意子序列连接起来,构成上升序列 
任意子序列处理起来比较麻烦,我们把问题转换成为整个序列单调不降,任意子序列都是单调不降的 
此时序列个数为 C C C  ,最后的答案就是 n 2 − C n^2 - C n 2 − C 
这样我们任意一个序列就可以用二元组 ( l i , r i ) (l_i, r_i) ( l i  , r i  )   表示,l i ← A [ 0 ] , r i ← A [ n − 1 ] l_i \leftarrow A[0], r_i \leftarrow A[n-1] l i  ← A [ 0 ] , r i  ← A [ n − 1 ]  
问题转换为求解满足 r i ⩾ l j , ( i , j ) r_i \geqslant l_j, \quad (i, j) r i  ⩾ l j  , ( i , j )   的序对
for   ∀ j :   x ← l j \textbf{for} \ \forall j: \ x \leftarrow l_j for   ∀ j :   x ← l j   ,在所有数中二分查找 
\quad   找到第一个满足 r i ⩾ x r_i \geqslant x r i  ⩾ x   的 r i r_i r i   ,[ r i , e n d ) [r_i, end) [ r i  , e n d )   即为能够取的所有值 
这里如果用一个二元组表示,要将 r i r_i r i    作为第一关键字,即 ( r i , l i ) (r_i, l_i) ( r i  , l i  ) 
C. New Year and Permutation  
这个问题比较 tricky ,其实观察后发现 
如果 [ l , r ] [l, r] [ l , r ]   是满足条件的子列,那么 [ min  i = l r p i ⋯ max  i = l r p i ] [\min_{i = l}^{r} p_i \cdots \max_{i = l}^{r} p_i] [ min i = l r  p i  ⋯ max i = l r  p i  ]   属于 [ l , r ] [l, r] [ l , r ]   这个子段 
所以可以将这个子段缩成一个点,子段的长度为 l e n = r − l + 1 len = r-l+1 l e n = r − l + 1 
长度为 n n n   的排列一共有 n − l e n + 1 n-len+1 n − l e n + 1   种长度为 l e n len l e n   的子段 
将子段缩点,剩下有 n − l e n n-len n − l e n   个数,用隔板法插入,一共有 n − l e n + 1 n-len+1 n − l e n + 1   种插入方式 
所以最后答案就是 ( n − l e n + 1 ) ⋅ ( n − l e n + 1 ) ⋅ ( l e n ) ! ⋅ ( n − l e n ) ! (n-len+1)\cdot (n-len+1) \cdot (len)! \cdot (n-len)! ( n − l e n + 1 ) ⋅ ( n − l e n + 1 ) ⋅ ( l e n ) ! ⋅ ( n − l e n ) !  
 
D. New Year and Conference  
题意,一门课有两个上课地点 a , b a, b a , b  ,在两个上课地点的时间不同,分别为 [ s a i , e a i ] , [ s b i , e b i ] [sa_i, ea_i], [sb_i, eb_i] [ s a i  , e a i  ] , [ s b i  , e b i  ]  
定义 venue-sensitive \text{venue-sensitive} venue-sensitive   如下,存在课程集合 S S S  ,size ( S ) ⩾ 2 \textbf{size}(S) \geqslant 2 size ( S ) ⩾ 2  
使得 S S S   中的所有课在地点 a a a   上课冲突,在 b b b   上不冲突;或者在 b b b   冲突,在 a a a   不冲突 
如果找不到 venue-sensitive \text{venue-sensitive} venue-sensitive   的课程集合,输出 yes \text{yes} yes  ,否则输出 no \text{no} no 
对于课程 i i i   用一个四元组 ( s a i , e a i , s b i , e b i ) (sa_i, ea_i, sb_i, eb_i) ( s a i  , e a i  , s b i  , e b i  )   表示,大致思路为 
先找出 [ s a , e a ] [sa, ea] [ s a , e a ]   存在重合(即在 a a a   上课重合)的集合 S S S  ,然后判断 S S S   中是否存在一组 ( i , j ) , i ≠ j (i, j), i \neq j ( i , j ) , i  = j   
使得 [ s b i , e b i ] ,   [ s b j , e b j ] [sb_i, eb_i], \ [sb_j, eb_j] [ s b i  , e b i  ] ,   [ s b j  , e b j  ]   不重合 ,即存在有 在 b b b   上课不重合的两门课 
如果找到了,说明存在 venue-sensitive \text{venue-sensitive} venue-sensitive  ,返回 true \text{true} true 
活动选择模型,可以先根据 s a i sa_i s a i    对所有活动排序,用 STL \text{STL} STL   容器 S S S   来维护所有活动  [ s a 1 ⋯ s a n ] [sa_1 \cdots sa_n] [ s a 1  ⋯ s a n  ]  
对于活动 i i i  ,[ s a i , e a i ] [sa_i, ea_i] [ s a i  , e a i  ]  ,在 S S S   中二分查找位置 p p p  ,使得 s a p > e a i sa_p > ea_i s a p  > e a i   
此时有 s a i ⩽ s a i + 1 ⩽ ⋯ ⩽ s a p − 1 ⩽ e a i sa_i \leqslant sa_{i+1} \leqslant \cdots \leqslant sa_{p-1} \leqslant ea_i s a i  ⩽ s a i + 1  ⩽ ⋯ ⩽ s a p − 1  ⩽ e a i   
也就是说,活动 i ,   [ s a i , e a i ] i, \ [sa_i, ea_i] i ,   [ s a i  , e a i  ]   与活动集 V = [ i + 1 , p − 1 ] V = [i+1, p-1] V = [ i + 1 , p − 1 ]   在地点 a a a   相交 
接下来要判断活动 i ,   [ s b i , e b i ] i, \ [sb_i, eb_i] i ,   [ s b i  , e b i  ]   与活动集 V = [ i + 1 , p − 1 ] V=[i+1, p-1] V = [ i + 1 , p − 1 ]   在地点 b b b   是否相交 
可以在一开始先针对地点 b b b   的活动建一个线段树 
只需在线段树中查询区间 [ i + 1 , p − 1 ] [i+1, p-1] [ i + 1 , p − 1 ]   的 maxS ,  minE \text{maxS}, \ \text{minE} maxS ,   minE  
如果 e b i < maxS  or   s b i > minE eb_i < \text{maxS} \ \textbf{or} \ sb_i > \text{minE} e b i  < maxS   or   s b i  > minE  
说明 V V V   中存在一个活动和活动 i i i   不重合,集合是 venue-sensitive \text{venue-sensitive} venue-sensitive   的 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class SegTree { public:     void build(int p, int l, int r) {         t[p].l = l, t[p].r = r;         if  (l >= r) {             t[p].maxS = a[l].sb;             t[p].minE = a[l].eb;             return ;         }         int mid = (l + r) >> 1;         build(p<<1, l, mid);          build(p<<1 |1, mid+1, r);        pull(p);     } }; bool solve  () {     sort(a+1, a+1+n);     // according to eb     seg.build(1, 1, n);     vector<int> V;     V.push_back(0);     for  (int i = 1; i <= n; i++) V.push_back(a[i].sa);          for  (int i = 1; i <= n; i++) {         int p = upper_bound(V.begin(), V.end(), a[i].ea) - V.begin();         p--;         int maxS = seg.find(1, i+1, p, 0);         int minE = seg.find(1, i+1, p, 1);         if  (a[i].eb < maxS || a[i].sb > minE) return  false ;     }     return  true ; } 
 
codeforces round 714 div2 
F. Swapping Problem  
很显然,对于最左边的情况,不论交换前后,绝对值都为 p i + 2 ⋅ over + p j p_i + 2\cdot \text{over} + p_j p i  + 2 ⋅ over + p j   
其中 p i , p j p_i, p_j p i  , p j    表示两条线段不相交部分,over \text{over} over   表示相交部分,结果不可能变好 
能够使得结果变好的情况,按照向量方向为从小到大,如图所示 ,可以分为两类 
根据 A i < B i A_i < B_i A i  < B i    和 B i < A i B_i < A_i B i  < A i    分为两类,{ X : A i < B i } ,   { Y : B i < A i } \{X: A_i < B_i\}, \ \{Y: B_i < A_i\} { X : A i  < B i  } ,   { Y : B i  < A i  }  
a n s = ∑ abs i − 2 ⋅ over , over ans = \sum {\text{abs}_i} - 2 \cdot \text{over}, \quad \text{over} a n s = ∑ abs i  − 2 ⋅ over , over   表示线段相交部分的长度 
这样可以初步设计出一种算法 
对于 A i < B i A_i < B_i A i  < B i   ,固定 A i A_i A i   ,在满足 B j ⩽ A i B_j \leqslant A_i B j  ⩽ A i    的条件下,找到最大的 A j A_j A j   
这样使得线段overlap部分最大 ,即 over ( ( A i , B i ) , ( B j , A j ) ) \text{over}((A_i, B_i), (B_j, A_j)) over ( ( A i  , B i  ) , ( B j  , A j  ) )   最大 
对于 B i < A i B_i < A_i B i  < A i   ,也是类似的 
 
具体的算法如下
每个集合 X ( A i → B i ) , Y ( B i → A i ) X(A_i \to B_i), \quad Y(B_i \to A_i) X ( A i  → B i  ) , Y ( B i  → A i  )   拆成两个集合,以便于之后按照第一关键字排序 
X 1 ( A i , B i ) , X 2 ( B i , A i ) , Y 1 ( B i , A i ) , Y 2 ( A i , B i ) X1(A_i, B_i), X2(B_i, A_i), Y1(B_i, A_i), Y2(A_i, B_i) X 1 ( A i  , B i  ) , X 2 ( B i  , A i  ) , Y 1 ( B i  , A i  ) , Y 2 ( A i  , B i  )  ,之后根据第一关键字排序
 
A i < B i A_i < B_i A i  < B i    的情况,遍历集合 X 1 X1 X 1  ,对于 ∀ A i \forall A_i ∀ A i   :
在集合 Y Y Y   中,找到满足 B j ⩽ A i B_j \leqslant A_i B j  ⩽ A i    的最大的 B j B_j B j   
此时 B j B_j B j    是关键字,所以 B j ∈ Y 1 B_j \in Y1 B j  ∈ Y 1  
遍历满足条件的 ∀ B j ∈ Y 1 \forall B_j \in Y1 ∀ B j  ∈ Y 1  ,将 B j B_j B j    所对应的 A j A_j A j    值用一个 set \textbf{set} set   来维护 
取 A j = set . r b e g i n ( ) A_j = \textbf{set}.rbegin() A j  = set . r b e g i n ( )  ,over ← max  { min  ( A j , B i ) − A i } \text{over} \leftarrow \max \{\min(A_j, B_i) - A_i\} over ← max { min ( A j  , B i  ) − A i  }  
 
 
B i < A i B_i < A_i B i  < A i    的情况也类似
 
最后 ∑ i ∣ A i − B i ∣ − 2 ⋅ over \sum_i |A_i - B_i| - 2\cdot \text{over} ∑ i  ∣ A i  − B i  ∣ − 2 ⋅ over   就是答案
 
 
Add One  
首先很容易想到一种数位dp的方法 
一开始的时候,统计 x x x   有那些数字,以第几次操作作为”阶段“,f ( i , b ) f(i, b) f ( i , b )   表示第 i i i   阶段,数字 b b b   的长度
f ( 0 , b ) = 1 , b ∈ digit ( x ) f ( i , b + 1 ) = f ( i , b + 1 ) + f ( i − 1 , b ) b ∈ [ 0 , 8 ] f ( i , 0 ) = f ( i , 0 ) + f ( i − 1 , 9 ) f ( i , 1 ) = f ( i , 1 ) + f ( i − 1 , 9 ) b = 9 \begin{aligned}
&f(0, b) = 1, \quad b \in \text{digit}(x) \\
&f(i, b+1) = f(i, b+1) + f(i-1, b) \quad b \in [0, 8] \\
&f(i, 0) = f(i, 0) + f(i-1, 9) \quad f(i, 1) = f(i, 1) + f(i-1, 9) \quad b = 9
\end{aligned}
  f ( 0 , b ) = 1 , b ∈ digit ( x ) f ( i , b + 1 ) = f ( i , b + 1 ) + f ( i − 1 , b ) b ∈ [ 0 , 8 ] f ( i , 0 ) = f ( i , 0 ) + f ( i − 1 , 9 ) f ( i , 1 ) = f ( i , 1 ) + f ( i − 1 , 9 ) b = 9  
但这样每个询问都必须重新计算遍,会超时,这里可以反着来  d p dp d p  
第 m m m   次操作视为阶段 0 0 0  ,因为每一次操作对数位的影响 ,是相互独立的,所以算法正确
b ∈ [ 0 , 8 ] b \in [0, 8] b ∈ [ 0 , 8 ]  ,第 i i i   阶段数字 b b b   的长度和第 i − 1 i-1 i − 1   阶段数字 b + 1 b+1 b + 1   的长度相等 
f ( i , b ) = f ( i − 1 , b + 1 ) f(i, b) = f(i-1, b+1) f ( i , b ) = f ( i − 1 , b + 1 )  
b = 9 b = 9 b = 9  ,第 i i i   阶段数字是 9 9 9  ,那么第 i − 1 → i i-1 \to i i − 1 → i   阶段存在 ( 0 → 9 ) , ( 1 → 9 ) (0 \to 9), (1 \to 9) ( 0 → 9 ) , ( 1 → 9 )   的转移 
换句话说,第 i i i   阶段 9 9 9   的长度来源于第 i − 1 i-1 i − 1   阶段 0 , 1 0, 1 0 , 1   贡献的长度 
f ( i , 9 ) = f ( i − 1 , 0 ) + f ( i − 1 , 0 ) f(i, 9) = f(i-1, 0) + f(i-1, 0) f ( i , 9 ) = f ( i − 1 , 0 ) + f ( i − 1 , 0 )  
最后统计 b ∈ [ 0 , 9 ] b \in [0, 9] b ∈ [ 0 , 9 ]  ,看看 b b b   中那些数在 x x x   的数位中出现,对 f ( m , b ) f(m, b) f ( m , b )   求和即可