CF1553(Div.1+Div.2) I 题解

8 篇文章 1 订阅
6 篇文章 0 订阅

前言

由于 NTT 是 10 10 10 级算法,所以本篇题解仅介绍到 O ( n 2 ) O(n^2) O(n2) 解法。

Description

给定一个长度为 n n n 的排列 p p p

令其中第 i i i 个位置的权值为最长的包含 i i i 的单调区间。例如, p = [ 4 , 1 , 2 , 3 , 7 , 6 , 5 ] p=[4,1,2,3,7,6,5] p=[4,1,2,3,7,6,5] 中,第 6 6 6 个位置的权值为 [ 5 , 7 ] [5,7] [5,7] 的长度,第 2 2 2 个位置的权值为 [ 2 , 4 ] [2,4] [2,4] 的长度。

将这些权值依次拼在一起,就得到了 p p p阶梯序列

给定 a a a,你需要求出存在多少个 p p p,使得 a a a p p p阶梯序列

1 ≤ n ≤ 1 0 5 1 \le n \le 10^5 1n105,时限 10s \texttt{10s} 10s,空限 1GB \texttt{1GB} 1GB

Solution

Part 1: 性质的分析与观察

根据阶梯序列的定义, a i a_i ai i i i 所属的极长单调区间长度。但是 i i i 既可以是这段区间的中间某个位置,也可以是两端的位置,考虑起来情况较多,较为困难。于是我们先考虑第一个位置,其只能作为单调区间的开头,思考起来较为容易。

x = a 1 x=a_1 x=a1。不难发现,此时 [ 1 , x ] [1,x] [1,x] 是一个极长单调区间。接下来,我们再考虑 p x + 1 p_{x+1} px+1,并令 x ′ = a x + 1 x'=a_{x+1} x=ax+1。不难发现, p x + 1 p_{x+1} px+1 不能与 [ 1 , x ] [1,x] [1,x] 合并成一个新的单调区间,且 [ x + 1 , x + x ′ ] [x+1,x+x'] [x+1,x+x] 也是一个极长的单调区间。以此类推,我们将序列划分为了若干个极长的单调区间。这样一来,我们就成功地将问题转化为:给定若干个区间,你需要往里面填数,使得序列构成一个排列,且每个给定的区间都是一个极长的单调区间,求方案数。

如果区间只要求单调,不要求极长,那么问题就十分简单了。由于每个区间的 p i p_i pi 在值域上都是连续的一段 [ L , R ] [L,R] [L,R],所以我们只需要钦定这些 [ L , R ] [L,R] [L,R] 的大小关系以及这些极长区间的增减性即可唯一确定 p p p。方案数不难通过组合数以及乘法原理写出。

若要求极长,问题变了复杂了起来。

注意到,若两段区间不可合并,那么限制会较为复杂;若必须合并,那么限制非常简单。这启发我们从反面考虑。但是,不可合并的相邻区间对太多了,这又启发我们容斥地计算。然而 n n n 较大,不能 2 n 2^n 2n 地枚举相邻对。

能否 dp \text{dp} dp 呢?

Part 2: dp 的设计与转移

为方便叙述,定义 s i s_i si 表示第 i i i 个区间的长度。

f i f_{i} fi 表示,仅考虑前 i i i 个区间的方案数。

根据容斥的基本思想,对于第 i + 1 i+1 i+1 个位置,它有两种选择:

  • violate the rule \text{violate the rule} violate the rule——它与前面的区间可以合并
  • follow the rule or not \text{follow the rule or not} follow the rule or not——无论它填什么都可以。

考虑动态地将第 i + 1 i+1 i+1 个区间插入进前 i i i 个区间的按值域左端点排序的序列。然而,无论对于前者(违反规则)还是后者(随意),插入的位置数似乎较难根据 i i i 直接确定(若插入到某个不恰当的位置,可能会将原来两个合并的区间断开)。

仔细分析——对于前者而言,若前面一个区间长度为 1 1 1,那么插入的位置有 2 2 2 个,否则只有 1 1 1 个;对于后者而言,令 j j j 为前 i i i 个区间中钦定可合并的次数,那么插入的位置树为 i − j + 1 i-j+1 ij+1 个。

从而,我们加维度 j j j,表示目前钦定合并的次数。同时,再加一维 k k k,表示上一个区间的长度是否为 1 1 1

总结一下最终的状态设计:令 f i , j , k f_{i,j,k} fi,j,k 表示,看了前 i i i 个区间,合并 j j j 次,上一个区间的长度为 1 1 1 或不为 1 1 1 的方案数。注意,这里的上一个区间长度不一定是 s i − 1 s_{i-1} si1,而可能是一个比它更大的值(因为 s i − 1 s_{i-1} si1 可能参与了多次合并,而使得上一个区间的长度较大)。

转移如下:

  • 钦定合并。
    f i − 1 , j , 0 → f i , j + 1 , 0 f_{i-1,j,0} \to f_{i,j+1,0} fi1,j,0fi,j+1,0 2 f i − 1 , j , 1 → f i , j + 1 , 0 2f_{i-1,j,1} \to f_{i,j+1,0} 2fi1,j,1fi,j+1,0

  • 钦定合并。

    • s i ≠ 1 s_i \neq 1 si=1,则
      2 ( i − j ) f i − 1 , j , 0 / 1 → f i , j , 0 2(i-j)f_{i-1,j,0/1} \to f_{i,j,0} 2(ij)fi1,j,0/1fi,j,0

    • s i = 1 s_i=1 si=1,则
      ( i − j ) f i − 1 , j , 0 / 1 → f i , j , 1 (i-j)f_{i-1,j,0/1} \to f_{i,j,1} (ij)fi1,j,0/1fi,j,1

这里容易出现一个错误,就是在转移的时候漏掉系数 2 2 2。由于长度超过 1 1 1 的区间的单调增与单调减是不同的,所以在向第三维为 0 0 0 的状态转移时,要额外乘上一个 2 2 2

边界:
①若 s 1 ≠ 1 s_1 \neq 1 s1=1 f 1 , 0 , 0 = 2 f_{1,0,0}=2 f1,0,0=2
②若 s 1 = 1 s_1=1 s1=1 f 1 , 0 , 1 = 1 f_{1,0,1}=1 f1,0,1=1
答案:

∑ i = 0 len ( − 1 ) i ( f n , i , 0 + f n , i , 1 ) \sum_{i=0}^{\text{len}} (-1)^i (f_{n,i,0}+f_{n,i,1}) i=0len(1)i(fn,i,0+fn,i,1)

时间复杂度 O ( n 2 ) O(n^2) O(n2)

//https://codeforces.ml/contest/1553/submission/123423493
for (int i=2;i<=len;i++){
	for (int j=0;j<=len;j++){
		chksum(f[i-1][j][0],f[i][j+1][0]);
		chksum(f[i-1][j][1],f[i][j+1][0],2);
		if (s[i]!=1){
			for (int k=0;k<2;k++)  chksum(f[i-1][j][k],f[i][j][0],2*(i-j));	
		}
		else{
			for (int k=0;k<2;k++)  chksum(f[i-1][j][k],f[i][j][1],i-j);
		}
	}
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,Codeforces Round 511 (Div. 1)是一个比赛的名称。然而,引用内容中没有提供与这个比赛相关的具体信息或问题。因此,我无法回答关于Codeforces Round 511 (Div. 1)的问题。如果您有关于这个比赛的具体问题,请提供更多的信息,我将尽力回答。 #### 引用[.reference_title] - *1* [Codeforces Round 860 (Div. 2)题解](https://blog.csdn.net/qq_60653991/article/details/129802687)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Codeforces Round 867 (Div. 3)(A题到E题)](https://blog.csdn.net/wdgkd/article/details/130370975)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Codeforces Round 872 (Div. 2)(前三道](https://blog.csdn.net/qq_68286180/article/details/130570952)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值