program
Description
对于一个仅有<、>、0~9组成字符串,执行一种操作,一开始指针在开头位置,指针移动方向默认为向右移,当遇到<或>,指针移动方向就要对应的修改成向左或向右。
当连续遇到两个非数字字符时,便要删掉前一个<或>。
若遇到了一个数字,便将此数打印出来,并将其数字-1,当发现一个数字在打印之前为0,打印后便将其删掉。
若指针移到了字符串外,结束整个过程。
现在给出一个长度为
n
的仅有<、>、0~9组成字符串,给出
Data Constraint
1
<=
Solution
在字符串的前面加入足够的>,然后从开头对整个串执行操作,记下每个时刻下每个数字的打印次数。
可以发现一个区间[
l
,
那显然这段时刻的开始点就是指针第一次到
l
位置的时间,结束点便是第一次到达
时间复杂度 O(10n+q)
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,j,l) for(int i=j;i<=l;++i)
#define fd(i,j,l) for(int i=j;i>=l;--i)
using namespace std;
typedef long long ll;
const ll M=31e5,K=1e9;
int n,q,x,y;
int qz[M][10];
char s[M];
int next[M],last[M],ne[M],la[M];
int f[M],g[M];
inline int min(int a,int b)
{return a<b?a:b;}
inline void erase(int p)
{ne[la[p]]=ne[p]; la[ne[p]]=la[p];}
int main()
{
cin>>n>>q;
scanf("%s",s+2*n+1);
fo(i,1,n*2)s[i]='>';
int dir=1,dq=n*2,now=n*2; f[now]=0;
fo(i,1,3*n+1)next[i]=ne[i]=i+1,last[i]=la[i]=i-1;
next[0]=ne[0]=1;
fo(i,0,3*n+1)f[i]=g[i]=K;
int k=1;
for(;now>0&&now<=(n*3);++k){
f[now]=min(f[now],k);
fo(i,0,9)qz[k][i]=qz[k-1][i];
if(s[now]>='0'&&s[now]<='9')++qz[k][s[now]-48];
else dir=s[now]=='<'?0:1;
int wz=dir==0?last[now]:next[now];
if(wz<=0||wz>n*11){
now=wz; continue;
}
if(s[now]>='0'&&s[now]<='9'){
s[now]=='0'?(last[next[now]]=last[now],next[last[now]]=next[now]):s[now]=s[now]-1;
if(dir==0){
g[now]=min(g[now],k);
for(;dq>wz;dq=la[dq])g[dq]=k,erase(dq);
}
}else{
if(s[wz]=='<'||s[wz]=='>'){
(last[next[now]]=last[now],next[last[now]]=next[now]);
}
if(dir==0){
g[now]=min(g[now],k);
for(;dq>wz;dq=la[dq])g[dq]=k,erase(dq);
}
}
now=wz;
for(;ne[dq]<=now;)dq=ne[dq];
for(;dq>now;)dq=la[dq];
}
if(now==(n*11)+1)f[now]=k;
fo(i,1,q){
scanf("%d%d",&x,&y);
int qm=f[x+2*n]-1,hm=min(f[y+2*n+1]-1,g[x+2*n]);
fo(l,0,9)printf("%d ",qz[hm][l]-qz[qm][l]);
puts("");
}
}