[CF1178 F2] Long Colorful Strip
F2 - Long Colorful Strip
很牛的题!
首先,我们可以将颜色相同的一段区间缩成一个点,那么每次加入一个新的颜色时,最多只能将其所覆盖的那个颜色所属的区间分成三部分(原本:00000000,加入1后\(\rightarrow\)0001111000),也就是增加了两个点,那么也就意味着最终所成的点的个数最多只有\(2*n-1\)个,这样的话,\(m\)看着很大,其实也就是\(O(N)\)级别的
对于这种区间覆盖的题,优先考虑区间\(dp\)
设\(dp[l][r]\)表示让区间\([l,r]\)合法的方案数,且满足\([l,r]\)中的颜色不会在\([l,r]\)外出现
设\(p\)为区间\([l,r]\)中最小的颜色,其出现的最早的位置为\(mn_p\),最晚的位置为\(mx_p\),那么显然有我们可以一开始就让\(p\)覆盖区间\([a,b]\)(\([mn_p,mx_p]\in[a,b]\)),那么就有转移式
\]
其中,对于\(dp[a][b]\),其实就是相当于对于\([a,b]\)的所有方案,直接在每种方案的第一个操作之前给\([a,b]\)覆盖上颜色\(p\)即可(总之就是让第一步变成用\(p\)覆盖\([a,b]\),具体的,若原本的方案没有这一步,加上即可;否则,若其原本只用\(p\)覆盖\([s,t]\)(\([s,t]\in[a,b]\),因为\(p\)也是\([a,b]\)中最小的值,所以原本的用\(p\)覆盖\([s,t]\)的这一步也一定是该方案中的第一步)将其补全成覆盖\([a,b]\)即可
但是可以发现,当\(a=l,b=r\)时,就转不了了,所以考虑将\(dp[a][b]\)拆开
因为\(p\)的最早出现位置为\(mn_p\),最晚出现位置为\(mx_p\),所以显然有所有处于\([mn_p,mx_p]\)中的颜色的出现区间范围也不会超过\([mn_p,mx_p]\),这也意味这\([mn_p,mx_p]\)将\([a,b]\)分隔成了三个区间\([a,mn_p-1],[mn_p,mx_p],[mx_p+1,b]\),这三个区间是“独立的”,即它们的颜色集合没有交集
证明的话可以从\(mn_p\)和\(mx_p\)这两个点下手,因为它们的颜色\(p\)是区间\([a,b]\)中最小的颜色,这就意味着区间\([a,b]\)中剩下的所有颜色都不会跨越它们,也就是没有颜色会覆盖上述三个区间中的任意两个,所以所有颜色只会待在对应的一个区间内
\]
其中\([i,j]\)表示所有不包含颜色\(p\)的、属于区间\([mn_p,mx_p]\)的极长区间,它实际上如何转移的和上文中\(对dp[a][b]\)的解释一致
所以我们就得到了最终的式子
\]
复杂度\(O(N^3)\)
代码中,只要保证了当前区间\([l,r]\)的最小颜色\(p\)的范围属于当前区间,在转移时因为其他转移给\(dp[l][r]\)的\(dp[x][y]\)会保证属于\([x,y]\)的所有颜色只属于\([x,y]\)中,所以最终就一定能保证\([l,r]\)中的所有颜色只属于\([l,r]\)中
也就是归纳证明即可
#include<bits/stdc++.h>
using namespace std;
const int N=505,M=1e6+5,MOD=998244353;
int n,m,col[M],dp[N<<1][N<<1],mn[N],mx[N];
void add(int &x,int y){ x+=y; if(x>=MOD) x-=MOD; }
int ad(int x,int y){ x+=y; if(x>=MOD) x-=MOD; return x; }
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
scanf("%d",&col[i]);
if(col[i]==col[i-1]) --i,--m;
else (!mn[col[i]])&&(mn[col[i]]=i),mx[col[i]]=i;
}
if(m>=(n<<1)) return puts("0"),0;
for(int i=1;i<=m+1;++i) for(int j=0;j<i;++j) dp[i][j]=1;
for(int len=1;len<=m;++len)
for(int l=1,r,p,a,b;l+len-1<=m;++l){
r=l+len-1,p=N,a=0,b=0;
for(int k=l;k<=r;++k) p=min(p,col[k]);
if(mn[p]<l||mx[p]>r) continue;
for(int k=l-1;k<=mn[p]-1;++k) add(a,1ll*dp[l][k]*dp[k+1][mn[p]-1]%MOD);
for(int k=mx[p];k<=r;++k) add(b,1ll*dp[mx[p]+1][k]*dp[k+1][r]%MOD);
dp[l][r]=1ll*a*b%MOD;
for(int i=mn[p]+1,j=mn[p];i<mx[p];i=(j+=2)){
for(;col[j+1]!=p;++j) ;
dp[l][r]=1ll*dp[l][r]*dp[i][j]%MOD;
}
}
printf("%d",dp[1][m]);
return 0;
}
[CF1178 F2] Long Colorful Strip的更多相关文章
- CF1178 F1 Short Colorful Strip
题目链接 题意 有个长度为\(m\)公分的布,要在上面每公分都染上颜色,整块布染恰好\(n(n=m)\)种颜色.颜色标号从\(1\)到\(n\).染色需遵循: 1.从颜色\(1\)到颜色\(n\)依次 ...
- CF1178F Short/Long Colorful Strip(DP)
说起来,这题好像也不难-- 先考虑 F1 怎么做. 既然别的方法都不行不如试试\(f_{i,j}\) 表示在刚刚准备开始涂 \([i,j]\) 中最小编号的颜色之前,整个区间是同色的,且最后能做到 \ ...
- Codeforces 1178F2. Long Colorful Strip
传送门 首先涂区间,那么区间最多有 $2n$ 个相邻位置不同的情况,并且连续相同的颜色可以合并起来 那么这样操作完以后,区间长度最多为 $2n$ 发现涂完一段区间以后其他的操作都不能出现一边在区间内而 ...
- Codeforces Global Round 4
目录 Contest Info Solutions A. Prime Minister B. WOW Factor C. Tiles D. Prime Graph E. Archaeology F1. ...
- python 多层装饰器
25.多层装饰器: 1.原理:执行顺序从上往下,#2和#3组成一个函数假设为nf1,#1和nf1组成一个函数nnf1 f1成为ck_ty_of_us的inner函数即nf ...
- python 的基础 学习 11天 作业题
1.整理函数相关知识点,写博客 2.写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者. def func1(argv): li = [] for i in r ...
- python基础学习11天,作业题
1. 文件a.txt内容:每一行内容分别为商品名字,价钱,个数. apple 10 3 tesla 100000 1 mac 3000 2 lenovo 30000 3 chicken 10 3 通过 ...
- python全栈开发day82-modelForm
1.jsonp内容 from django.shortcuts import render # Create your views here. def upload(request): if requ ...
- Python基础-day02
写在前面 上课第二天,打卡: 大人不华,君子务实. 一.进制相关 - 进制基础 数据存储在磁盘上或者内存中,都是以0.1形式存在的:即是以 二进制 的形式存在: 为了存储和展示,人们陆续扩展了数据的表 ...
- Python基础-day01
写在前面 先后接触过很多编程语言,最喜欢的就是C和Python,相比其他语言,C 是神器,优点太多了:个人而言,C 最重要的一点就是能够让你在敲代码的时候是以一个计算机科学家的角度去思考,而不是仅仅停 ...
随机推荐
- Linux系统运维之Zookeeper集群配置
一.简介 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.ZooKeeper的目标就是封装好复杂易 ...
- prometheus Histogram 统计原理
大家好,我是蓝胖子,书接上文,我在prometheus描点原理那一篇文章里,留了一个思考题: 我们通常会用到histogram_quantile去计算服务接口时间的耗时情况. histogram_qu ...
- .net 6 winform启动器:调用CMD命令行执行dotnet命令启动.net core程序并将控制台输出日志输出到winform textbox实现实时日志显示
背景 历史遗留问题,生产车间运行的一个.net core signalr程序使用命令行程序启动,经常由于生产人员误操作将光标停留在控制台上导致程序假死,丢失部分测试数据,车间随便找了一台win10系统 ...
- PaddleSharp:跨越一年的版本更新与亮点
PaddleSharp:跨越一年的版本更新与亮点 我始终坚信,开源社区是技术进步的重要推动力,也是我抽出我业余时间,投入到PaddleSharp这个项目的原因,这个项目充分展现了.NET在复杂计算领域 ...
- rman catalog 遇到的一个错误
[oracle@source admin]$ sqlplus / as sysdba SQL*Plus: Release 11.2.0.3.0 Production on Thu Jun 22 09: ...
- 清理MySQL的binlog历史文件
前言 系统版本:centos 7 MySQL版本:5.7 mysql的binlog文件最好不要手动删,避免删错导致bin log同步异常. 步骤 查看当前的binlog文件 show binary l ...
- python命令行解析模块argparse
argparse是Python标准库中推荐的命令行解析模块 code01: tmp.py import argparse parser = argparse.ArgumentParser(descri ...
- python中将时间转换为时间戳
某平台url中的时间格式为时间戳,将时间变量传入url前,需要将固定格式的时间转换为时间戳.使用python中的time模块,对时间的几种格式进行转换. strptime(),将时间字符串转换成 结构 ...
- Log4j疯狂写日志问题排查
一.问题是怎么发现的 最近有个 Java 系统上线后不久就收到了磁盘使用率告警,磁盘使用率已经超过了 90% 以上,并且磁盘使用率还在不停增长. 二.问题带来的影响 由于服务器磁盘被打满,导致了系统正 ...
- ES集群&kibana安装
一.elasticsearch介绍 Elasticsearch 是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful 风格接口,多数据源,自动搜索负 ...