\(\mathcal{Description}\)

  给定排列 \(\{p_n\}\),可以在其上进行若干次操作,每次选取 \([l,r]\),把其中所有元素变为原区间最小值,求能够得到的所有不同序列数量。答案对 \((10^9+7)\) 取模。

  \(n\le5\times10^3\)。

\(\mathcal{Solution}\)

  一类题型一起写啦,再给出一道类似的题:

  给定字符串 \(s\),\(s_i\in\{\text{'R'},\text{'G'},\text{'Y'}\}\),每次允许交换相邻两个元素。求最少交换次数,使得 \(s\) 中不存在两个相邻元素相等,或声明无解。

  \(n\le400\)。

  不难看出它们都是 DP 题,但是若以从左到右的视角考虑问题,给定的操作具有强后效性,很难设计出一种靠谱的状态。

  这个时候可以奉行“拿来主义”(?),直接构造结果序列,将问题转化为把原序列上某值拿到结果序列的某位置的最小操作次数 / 方案数,再根据实际情况设计算法就很方便了。

  例如,对于求方案数的这题,令 \(f(i,j)\) 表示构造了结果序列的前 \(i\) 位,第 \(i\) 位用的是原序列的 \(p_j\) 的方案数。根据较大值不能覆盖较小值设计转移即可;对于最小化操作次数这题,令 \(f(i,r,g,k\in\{0,1,2\})\) 表示构造了结果序列前 \(i\) 位,用了 \(r\) 个 R,\(g\) 个 G,(\((i-r-g)\) 个 Y,)最后一个位置颜色为 \(k\) 的最小代价。转移利用类似冒泡排序的性质,在原序列里拿一个最近的颜色到当前位置即可。

\(\mathcal{Code}\)

  只给那道计数题的代码叭。

/*-Rainybunny-*/

#include <bits/stdc++.h>

#define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i ) const int MAXN = 5e3, MOD = 1e9 + 7;
int n, a[MAXN + 5], lef[MAXN + 5], rig[MAXN + 5], f[2][MAXN + 5]; inline void addeq( int& u, const int v ) { ( u += v ) >= MOD && ( u -= MOD ); } inline void init() {
static int stk[MAXN + 5]; int top = 0;
rep ( i, 1, n ) {
while ( top && a[stk[top]] >= a[i] ) --top;
lef[i] = stk[top] + 1, stk[++top] = i;
}
stk[top = 0] = n + 1;
per ( i, n, 1 ) {
while ( top && a[stk[top]] >= a[i] ) --top;
rig[i] = stk[top] - 1, stk[++top] = i;
}
} int main() {
freopen( "C.in", "r", stdin );
freopen( "C.out", "w", stdout ); scanf( "%d", &n );
rep ( i, 1, n ) scanf( "%d", &a[i] ); init();
rep ( i, 1, n ) if ( lef[i] == 1 ) f[1][i] = 1;
for ( int sta = 1, i = 2; i <= n; sta ^= 1, ++i ) {
rep ( j, 1, n ) f[!sta][j] = rig[j] >= i ? f[sta][j] : 0;
int s = 0;
rep ( j, 1, n ) {
if ( lef[j] <= i && i <= rig[j] ) addeq( f[!sta][j], s );
addeq( s, f[sta][j] );
}
} int ans = 0;
rep ( i, 1, n ) addeq( ans, f[n & 1][i] );
printf( "%d\n", ans );
return 0;
}

最新文章

  1. 最新WingIDE注册破解方法 【转】
  2. String.Format格式说明——复制于DotNet笔记
  3. thttpd和cgilua安装与运行流程分析
  4. iOS9 判断微信qq是否安装
  5. 大话Git
  6. html5定位并在百度地图上显示
  7. CICS&amp;&amp;XA
  8. jQuery 点击按钮刷新页面
  9. Entity Framework Code First主外键关系映射约定
  10. HDU 1997 汉诺塔VII
  11. 基于visual Studio2013解决C语言竞赛题之0608水仙花函数
  12. 关于echarts、layer.js和jqGrid的知识点
  13. inode满处理
  14. 聚宽获取财务数据+DataFrame写入txt
  15. 3.有关于Python列表简述
  16. selenium_UI自动化——篇1(基础)
  17. js转义和反转义html htmlencode htmldecode
  18. vpnbook.py
  19. 【Alpha】阶段第十次Scrum Meeting
  20. centos 7 sshd 重启 停止 启动

热门文章

  1. Eclipse导包
  2. Zabbix监控报警Lack of free swap space on Zabbix server解决办法
  3. vue注册全局组件
  4. linux下玩转磁盘管理与挂载硬盘
  5. 【Java】简单了解网络编程
  6. 获取app启动时间
  7. 手把手教你分析解决MySQL死锁问题
  8. 洛谷 CF196A 题解
  9. 【记录一个问题】opencl enqueueWriteBuffer()中,cl_bool blocking参数设置无效
  10. C++构造函数语义学(一)(基于C++对象模型)