当前位置: 代码迷 >> 综合 >> bzoj 4881: [Lydsy1705月赛]线段游戏
  详细解决方案

bzoj 4881: [Lydsy1705月赛]线段游戏

热度:110   发布时间:2023-10-29 05:04:33.0

链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4881

一个正解比较优秀的题,但是可以被各种乱搞搞过的题。。
首先题目的意思就是要你分成两个上升子序列问你有多少方案

先说一个复杂的方法
考虑DP,fif_ifi?表示第一个子序列以i结尾且[1,i?1][1,i-1][1,i?1]里面第二个子序列的最后一位比i+1i+1i+1小的方案有多少个
那么答案就是我们从后往前扫,如果[i,n][i,n][i,n]是递增的,那么就加上fif_ifi?
至于转移,可以枚举第二个子序列的最后一个jjj,那么显然要满足[j+1,i][j+1,i][j+1,i]是递增的,那么fif_ifi?就加上fjf_jfj?
容易发现jjj是连续的一段
那么jjj就要满足两个限制,第一个是aj&lt;ai+1a_j&lt;a_i+1aj?<ai?+1,第二个是L&lt;=j&lt;=i?1L&lt;=j&lt;=i-1L<=j<=i?1
对于权值开个树状数组维护即可

然后说一个可能没那么复杂的方法
考虑找到全串的最大值的位置,设为AAA
那么显然AAA[A+1,n][A+1,n][A+1,n]必须分为两段
把这两段的开头设为AAA,BBB
然后把[A,n][A,n][A,n]删掉,变为一个子问题
考虑把两段合并
设前面一段的最大值位置为nownownow,这个的第二段是now1(当然有不存在的情况,随便判判就好了)
那么有两个合并方法,第一个是nownownow接在AAA前面,第二个是接在BBB前面
容易发现,第一个是一定可以接上的,如果可以接上第二个,那么就有两个接法,否则就是一个
不难发现,相接以后,两个方案都等价于A变为now,如果有now1的话,B变为now1,否则不变
无解的情况当且仅当[now1,A][now1,A][now1,A]不是递增的,暴力判就好了
容易发现,整个过程是线性的,如果用基数排序实现排序的话就可以做到O(n)O(n)O(n)

最后说一下正解的方法
如果最长下降子序列>=3,那么就就显然无解了
那么剩下就都是有解的
把这个判掉,考虑一个暴力做法
就是逆序对之间连边,那么答案就是2∣联通块个数∣2^{|联通块个数|}2
容易发现边数是O(n2)O(n^2)O(n2)
但其实,如果你从前往后扫,对于每一个连通块,显然只需要记录最大值就够了
因此得到一个做法,就是每扫到一个数,就把之前比他大的都拿出来,合并成一个最大的丢回去
最后看看有多少个元素,就是连通块的个数了
整个过程可以用一个set来维护,那么复杂度就是O(nlogn)O(nlogn)O(nlogn)

以上就是本题暂时能想到的三个方法,各位看官挑一个自己喜欢的做法吧。。
我个人就是第二个。。但感觉代码贴出来就不好看了,那么就自己实现吧(雾