hello 2019;题意:
给出区间,要你在查询区间内有9102,同时没有8012的序列,需要删除多少个数字。
多次询问,所以给上我们的线段树。
这道题有原题;
我们dp表示i从状态i到状态j的操作次数,
我们定义0,1,2,3,4为"",2,20,201,2017的状态。对于每个状态用矩阵表示:
如dp【1】【2】从状态为2到20;
例如我们看其中一个地方{
if(s[l]=='2') p[cur].a[0][0]=1,p[cur].a[0][1]=0;
表示此刻遇到了2,那么就0状态的“”到“”,要花费1
为什么呢,也就是我们“”遇到2,应变为2,但是你想保持“",那么就得删掉2,其他同理,
然后就来到但是到6的时候,保持201到201需要删除6,花费价值为1。因为不能出现2016,所以从2017转移也需要删除一个价值。
}
代码给上:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxx=2e5+100;
struct node{
int a[5][5];
node operator+(const node &b)const//重载加法
{
node c;
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
{
c.a[i][j]=inf;
for(int k=0;k<5;k++)
c.a[i][j]=min(c.a[i][j],a[i][k]+b.a[k][j]);
}
}
return c;
}
}p[maxx<<2];
char s[maxx];
int n,m;
inline void pushup(int cur)
{
p[cur]=p[cur<<1]+p[cur<<1|1];
}
inline void build(int l,int r,int cur)
{
if(l==r)
{
for(int i=0;i<5;i++)for(int j=0;j<5;j++) p[cur].a[i][j]=(i==j)?0:inf;
if(s[l]=='2') p[cur].a[0][0]=1,p[cur].a[0][1]=0;
else if(s[l]=='0') p[cur].a[1][1]=1,p[cur].a[1][2]=0;
else if(s[l]=='1') p[cur].a[2][2]=1,p[cur].a[2][3]=0;
else if(s[l]=='7') p[cur].a[3][3]=1,p[cur].a[3][4]=0;
else if(s[l]=='6') p[cur].a[3][3]=1,p[cur].a[4][4]=1;
return ;
}
int mid=l+r>>1;
build(l,mid,cur<<1);
build(mid+1,r,cur<<1|1);
pushup(cur);
}
inline node query(int L,int R,int l,int r,int cur)
{
if(l<=L&&R<=r) return p[cur];
int mid=L+R>>1;
if(r<=mid) return query(L,mid,l,r,cur<<1);
else if(l>mid) return query(mid+1,R,l,r,cur<<1|1);
else return query(L,mid,l,mid,cur<<1)+query(mid+1,R,mid+1,r,cur<<1|1);
}
int main()
{
int l,r;
while(~scanf("%d%d",&n,&m))
{
scanf("%s",s+1);
build(1,n,1);
while(m--)
{
scanf("%d%d",&l,&r);
node ans=query(1,n,l,r,1);
if(ans.a[0][4]==inf) printf("-1\n");
else printf("%d\n",ans.a[0][4]);
}
}
return 0;
}
然后2019这道题就洒洒水地将序列反转变成找2019,不要2018,所以他给出区间后,你也得反转一下再询问,
代码如下:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxx=2e5+100;
struct node{
int a[5][5];
node operator+(const node &b)const
{
node c;
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
{
c.a[i][j]=inf;
for(int k=0;k<5;k++)
c.a[i][j]=min(c.a[i][j],a[i][k]+b.a[k][j]);
}
}
return c;
}
}p[maxx<<2];
char s[maxx],ss[maxx];
int n,m;
inline void pushup(int cur)
{
p[cur]=p[cur<<1]+p[cur<<1|1];
}
inline void build(int l,int r,int cur)
{
if(l==r)
{
for(int i=0;i<5;i++)for(int j=0;j<5;j++) p[cur].a[i][j]=(i==j)?0:inf;
if(s[l]=='2') p[cur].a[0][0]=1,p[cur].a[0][1]=0;
else if(s[l]=='0') p[cur].a[1][1]=1,p[cur].a[1][2]=0;
else if(s[l]=='1') p[cur].a[2][2]=1,p[cur].a[2][3]=0;
else if(s[l]=='9') p[cur].a[3][3]=1,p[cur].a[3][4]=0;
else if(s[l]=='8') p[cur].a[3][3]=1,p[cur].a[4][4]=1;
return ;
}
int mid=l+r>>1;
build(l,mid,cur<<1);
build(mid+1,r,cur<<1|1);
pushup(cur);
}
inline node query(int L,int R,int l,int r,int cur)
{
if(l<=L&&R<=r) return p[cur];
int mid=L+R>>1;
if(r<=mid) return query(L,mid,l,r,cur<<1);
else if(l>mid) return query(mid+1,R,l,r,cur<<1|1);
else return query(L,mid,l,mid,cur<<1)+query(mid+1,R,mid+1,r,cur<<1|1);
}
int main()
{
int l,r;
while(~scanf("%d%d",&n,&m))
{
scanf("%s",ss+1);
for(int i=1;i<=n;i++) s[i]=ss[n-i+1];
build(1,n,1);
while(m--)
{
scanf("%d%d",&l,&r);
node ans=query(1,n,n-r+1,n-l+1,1);
if(ans.a[0][4]==inf) printf("-1\n");
else printf("%d\n",ans.a[0][4]);
}
}
return 0;
}
//感谢大佬地博客:https://blog.csdn.net/starlet_kiss/article/details/100694910