链表+模拟
VFK题解:应该能注意到这个编程语言有特殊性质即指针的移动是连续的,这意味着假设我们在开头处放置足够多的“>”,那么单独取一个区间出来执行时的程序一定是完整地执行整个代码的程序的一部分。于是我们可以做一个前缀和。f[i][d] 表示第i 个字符在准备第一次访问到的时候数字d 输出了多少次,g[i][d] 表示第i 个字符在指针准备从此处向左移走的时候数字d 输出了多少次。然后查询一段区间时,程序肯定从左端点开始执行,但有可能从左边或者右边出去。于是我们可以比较下左端点的f 和右端点的g 的时间,然后安心地使用前缀和相减得到结果。
说是这么说的,然而代码实现卡了我差不多一个下午。。。用链表模拟要注意如”00000<”的串,在查询[3,6]时是无法得到3处准备左移的时间的,因为在做第3位的时候3已经被删掉了。。。因此为了防止这种情况发生,在orz了汪队的代码之后,我发现更新左移最早时间只需要把它们都压到栈里,等到指针左移时暴力把下标在左移的区间内的栈内元素更新即可。。。(顺便吐槽一下,CF上很多代码时间复杂度是错的(?),只要用”>9>9>9>9>9…<9<9<9<9<9”这种就能卡掉,我该说啥好。。。)
话说这题真有意思呀,tourist考场上都没敲出来呢。。。
#include<cstdio>
#include<cstring>
#define N 100005
#define A 10
#define cmin(u,v) (u)>(v)?(u)=(v):0
using namespace std;
namespace runzhe2000
{
const int INF = 1<<29;
int ft[N], gt[N], f[N][10], g[N][10], timer = 1, c[10], sta[N], top;
char s[N]; bool insta[N];
struct node
{
int l, r, v;
}no[N];
void del(int x)
{
no[no[x].l].r = no[x].r;
no[no[x].r].l = no[x].l;
}
void main()
{
int n, q; scanf("%d%d%s",&n,&q,s+1);
for(int i = 1, v; i <= n; i++)
{
if(s[i] >= '0' && s[i] <= '9') v = s[i] - '0';
else v = s[i] == '<' ? 11 : 10;
no[i] = (node){i-1, i+1, v};
}
memset(ft,63,sizeof(ft));
memset(gt,63,sizeof(gt));
++timer; ++n;
no[n] = (node){n-1,n+1,10};
for(int l = 1; l <= n; l++) if(ft[l] > INF)
{
for(int cur = l, next, pos = 10; l <= cur && cur <= n; cur = next, ++timer)
{
if(timer < ft[cur])
{
ft[cur] = timer;
for(int i = 0; i < A; i++)
f[cur][i] = c[i];
}
if(no[cur].v < 10)
{
c[no[cur].v--]++;
if(no[cur].v < 0) del(cur);
}
else
{
pos = no[cur].v;
}
next = pos==11?no[cur].l:no[cur].r;
if(no[cur].v > 9 && no[next].v > 9) del(cur);
if(!insta[cur])sta[++top] = cur, insta[cur] = 1;
if(pos == 11)
{
for(; no[cur].l < sta[top] && sta[top] <= cur && top; --top)
{
gt[sta[top]] = ++timer;
for(int i = 0; i < A; i++)
g[sta[top]][i] = c[i];
}
}
}
}
for(; q--; )
{
int l, r; scanf("%d%d",&l,&r);
if(ft[r+1] < gt[l])
{
for(int i = 0; i < 10; i++)
printf("%d%c",f[r+1][i] - f[l][i],i==9?'\n':' ');
}
else
{
for(int i = 0; i < 10; i++)
printf("%d%c",g[l][i] - f[l][i],i==9?'\n':' ');
}
}
}
}
int main()
{
runzhe2000::main();
}