Codeforces 750E - New Year and Old Subsequence(线段树维护矩阵乘法,板子题)
u1s1 我做这道 *2600 的动力是 wjz 出了道这个套路的题,而我连起码的思路都没有,wtcl/kk
首先考虑怎样对某个固定的串计算答案,这显然可以 \(dp\) 解决,设 \(dp_{i,j}\) 表示考虑前 \(i\) 个字符,删去之后与 \(2017\) 的 LCS 为 \(j\),最少需删除多少个字符,那么显然有转移方程:
- \(dp_{i,0}=\begin{cases}dp_{i-1,0}&(s[i]\neq'2')\\dp_{i-1,0}+1&(s[i]='2')\end{cases}\)
- \(dp_{i,1}=\begin{cases}dp_{i-1,0}&(s[i]\neq'0'\land s[i]\neq'2')\\\min(dp_{i-1,1},dp_{i-1,0})&(s[i]='2')\\dp_{i-1,0}+1&(s[i]='0')\end{cases}\)
- \(dp_{i,2}=\begin{cases}dp_{i-1,1}&(s[i]\neq'1'\land s[i]\neq'0')\\\min(dp_{i-1,2},dp_{i-1,0})&(s[i]='0')\\dp_{i-1,1}+1&(s[i]='1')\end{cases}\)
- \(dp_{i,3}=\begin{cases}dp_{i-1,3}&(s[i]\neq'7'\land s[i]\neq'1'\land s[i]\neq'6')\\\min(dp_{i-1,3},dp_{i-1,2})&(s[i]='1')\\dp_{i-1,2}+1&(s[i]='6'\lor s[i]='7')\end{cases}\)
- \(dp_{i,4}=\begin{cases}dp_{i-1,4}&(s[i]\neq'7'\land s[i]\neq'6')\\\min(dp_{i-1,4},dp_{i-1,3})&(s[i]='7')\\dp_{i-1,4}+1&(s[i]='6')\end{cases}\)
初始值为 \(dp_{0,0}=0,dp_{0,i}=-\infty(i>0)\)。
注意到像这样的常系数其次线性递推式可以写成矩阵的形式,也就是说对于每个字符 \(s_i\) 都可以找到一个 \(4\times 4\) 矩阵 \(A_i\) 使得 \(\begin{bmatrix}dp_{i,0}\\dp_{i,1}\\dp_{i,2}\\dp_{i,3}\\dp_{i,4}\end{bmatrix}=A_i\times\begin{bmatrix}dp_{i-1,0}\\dp_{i-1,1}\\dp_{i-1,2}\\dp_{i-1,3}\\dp_{i-1,4}\end{bmatrix}\),也就是说对于一组询问 \([l,r]\),如果我们记 \(B_i=\begin{bmatrix}dp_{i,0}\\dp_{i,1}\\dp_{i,2}\\dp_{i,3}\\dp_{i,4}\end{bmatrix}\),那么有 \(B_r=A_r\times B_{r-1}=A_r\times A_{r-1}\times B_{r-2}=A_r\times A_{r-1}\times\dots A_l\times B_{l-1}\),而显然有 \(B_{l-1}=\begin{bmatrix}0\\-\infty\\-\infty\\-\infty\\-\infty\end{bmatrix}\),故最终的答案为 \((\prod\limits_{i=l}^rA_i)\times \begin{bmatrix}0\\-\infty\\-\infty\\-\infty\\-\infty\end{bmatrix}\)。不难发现这个东西是以区间乘法的形式出现的,而矩阵又不支持除法,故可以想到我们喜闻乐见的线段树。简单维护一下即可。
时间复杂度 \(q\omega^3\log n\),其中 \(\omega\) 为矩阵大小,在此题中为 \(5\)。
这个套路(线段树维护矩阵乘法)就是动态 dp(ddp) 的大致思想,比较毒瘤的动态 dp 一般还需套个树剖什么的。不过由于我太懒了就暂且不继续学 ddp 了(
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=2e5;
const int INF=0x3f3f3f3f;
int n,qu;char str[MAXN+5];
struct matrix{
int a[5][5];
matrix(){memset(a,63,sizeof(a));}
matrix operator *(const matrix &rhs){
matrix ret;
for(int i=0;i<5;i++) for(int j=0;j<5;j++) for(int k=0;k<5;k++)
chkmin(ret.a[i][j],a[i][k]+rhs.a[k][j]);
return ret;
}
};
struct node{int l,r;matrix v;} s[MAXN*4+5];
void build(int k,int l,int r){
s[k].l=l;s[k].r=r;if(l==r){
for(int i=0;i<5;i++) s[k].v.a[i][i]=0;
if(str[l]=='2') s[k].v.a[0][0]=1,s[k].v.a[0][1]=0;
if(str[l]=='0') s[k].v.a[1][1]=1,s[k].v.a[1][2]=0;
if(str[l]=='1') s[k].v.a[2][2]=1,s[k].v.a[2][3]=0;
if(str[l]=='7') s[k].v.a[3][3]=1,s[k].v.a[3][4]=0;
if(str[l]=='6') s[k].v.a[3][3]=1,s[k].v.a[4][4]=1;
return;
} int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
s[k].v=s[k<<1].v*s[k<<1|1].v;
}
matrix query(int k,int l,int r){
if(l<=s[k].l&&s[k].r<=r) return s[k].v;
int mid=s[k].l+s[k].r>>1;
if(r<=mid) return query(k<<1,l,r);
else if(l>mid) return query(k<<1|1,l,r);
else return query(k<<1,l,mid)*query(k<<1|1,mid+1,r);
}
int main(){
scanf("%d%d%s",&n,&qu,str+1);build(1,1,n);
while(qu--){
int l,r;scanf("%d%d",&l,&r);int ret=query(1,l,r).a[0][4];
if(ret>=INF) puts("-1");else printf("%d\n",ret);
}
return 0;
}
Codeforces 750E - New Year and Old Subsequence(线段树维护矩阵乘法,板子题)的更多相关文章
- Codeforces 1368H - Breadboard Capacity(最小割+线段树维护矩阵乘法)
Easy version:Codeforces 题面传送门 & 洛谷题面传送门 Hard version:Codeforces 题面传送门 & 洛谷题面传送门 首先看到这种从某一种颜色 ...
- Codeforces 750E New Year and Old Subsequence 线段树 + dp (看题解)
New Year and Old Subsequence 第一感觉是离线之后分治求dp, 但是感觉如果要把左边的dp值和右边的dp值合起来, 感觉很麻烦而且时间复杂度不怎么对.. 然后就gun取看题解 ...
- Codeforces 750E New Year and Old Subsequence - 线段树 - 动态规划
A string t is called nice if a string "2017" occurs in t as a subsequence but a string &qu ...
- Subsequence Count 2017ccpc网络赛 1006 dp+线段树维护矩阵
Problem Description Given a binary string S[1,...,N] (i.e. a sequence of 0's and 1's), and Q queries ...
- hdu 5068 线段树维护矩阵乘积
http://acm.hdu.edu.cn/showproblem.php?pid=5068 题意给的略不清晰 m个询问:从i层去j层的方法数(求连段乘积)或者修改从x层y门和x+1层z门的状态反转( ...
- 线段树维护矩阵【CF718C】 Sasha and Array
Description 有一个长为\(n\)的数列\(a_{1},a_{2}...a_{n}\),你需要对这个数列维护如下两种操作: \(1\space l \space r\space x\) 表示 ...
- CF718C Sasha and Array(线段树维护矩阵)
题解 (不会矩阵加速的先去学矩阵加速) 反正我想不到线段树维护矩阵.我太菜了. 我们在线段树上维护一个区间的斐波那契的列矩阵的和. 然后询问时提取每个符合题意列矩阵的答案项(不是列矩阵存了两项吗,一个 ...
- HDU 6155 Subsequence Count 线段树维护矩阵
Subsequence Count Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 256000/256000 K (Java/Oth ...
- Codeforces 719E (线段树教做人系列) 线段树维护矩阵
题面简洁明了,一看就懂 做了这个题之后,才知道怎么用线段树维护递推式.递推式的递推过程可以看作两个矩阵相乘,假设矩阵A是初始值矩阵,矩阵B是变换矩阵,求第n项相当于把矩阵B乘了n - 1次. 那么我们 ...
随机推荐
- FastAPI 学习之路(五十四)startup 和 shutdown
我们在实际的开发中呢,总会遇到这样的场景,我们想在启动或者终止的时候,做一些事情,那么应该如何实现呢,其实也是很简单.fastapi提供了这样的操作. 那么我们看下具体是怎么实现的呢 app = Fa ...
- [对对子队]会议记录5.25(Scrum Meeting11)
今天已完成的工作 吴桐雨 工作内容:设计第10.11关 相关issue:设计额外关卡 相关签入:level10 level11 吴昭邦 工作内容:写测试代码 相关issue:测试初 ...
- 算法:杨辉三角(Pascal's Triangle)
一.杨辉三角介绍 杨辉三角形,又称帕斯卡三角形.贾宪三角形.海亚姆三角形.巴斯卡三角形,是二项式系数的一种写法,形似三角形,在中国首现于南宋杨辉的<详解九章算法>得名,书中杨辉说明是引自贾 ...
- 15个问题自查你真的了解java编译优化吗?
摘要:为什么C++的编译速度会比java慢很多?二者运行程序的速度差异在哪? 了解了java的早期和晚期过程,就能理解这个问题了. 本文分享自华为云社区<你真的了解java编译优化吗?15个问题 ...
- vue2强制刷新,解决页面不会重新渲染的问题
问题描述: 在使用Vue框架开发时,在函数中改变了页面中的某个值,在函数中查看是修改成功了,但在页面中没有及时刷新改变后的值: 解决: 运用 this.$forceUpdate(); //强制刷新, ...
- linux 关于 环境变量
有关环境变量的文件 系统级环境变量:每一个登录到系统的用户都能够读取到系统级的环境变量 用户级环境变量:每一个登录到系统的用户只能够读取属于自己的用户级的环境变量 文件加载顺序: ==& ...
- Mac 搭建后端PHP+Go环境
准备工作 1. 安装brew命令 #很慢很慢.. ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/insta ...
- 2020 ICPC 沈阳站 I - Rise of Shadows 题解
题面看这里 \(PS\):符号 \([\ \rm P\ ]\) 的意义是:当表达式 \(\rm P\) 为真则取值为 \(1\),为假则取值为 \(0\). 题目大意 给你一个一天有 \(H\) ...
- istio ServiceMesh
什么是ServiceMesh?什么是Istio? 微服务的一种概念,随着微服务的来临,衍生出一系列的问题,比如服务发现.负载均衡.路由.流量控制.服务间通讯的可靠性.微服务的监控等一系列的问题.使用a ...
- 合并代码操作 | git fetch 与 git pull
前言 首先我们要说简单说git的运行机制.git分为本地仓库和远程仓库,我们一般情况都是写完代码,commit到本地仓库(生成本地仓的commit ID,代表当前提交代码的版本号),然后push到远程 ...