Portal --> broken qwq
Solution
怎么感觉自己在。。想这种子问题转化的时候总是容易出车祸Q^Q
假设当前我们有的串是([---A---][-B-]),其中(B)的长度就是(k),然后一次操作之后我们可以得到的是([---A---][-B-][-B-][---A---])
对于一个查询([l,r]),我们可以转化成查询([1,r])和查询([1,l-1]),现在考虑查询([1,x])怎么做:我们考虑一次一次操作往前推,假设当前是第(tm)次操作之后得到的串,我们要查询这个串的第(x)位,我们记上面第一个([-B-])的结尾位置为(mid)(其实就是第(tm-1)次操作之后得到的串),第二个([-B-])的结尾位置为(p),有一下几种情况:
1、如果说(x<=mid),那么说明这个位置在第(tm-1)甚至更少次操作之后就可以确定下来了,递归处理查询(tm-1)次操作之后的第(x)个位置
2、如果说(mid<x<=p),那么说明这个位置在第(tm)次操作中确定,并且注意到每次操作之后新增的都是一段原字符串,只是其中字符顺序不同罢了,所以我们可以直接将前(tm-1)次操作中新增的那些完整的原字符串的数量(也就是(tm-1))*原字符串中该字符的出现次数作为(mid)以前的贡献,然后(midsim x)的贡献,因为(k)很小并且最大的操作次数其实最多到(60)多,所以可以直接用一个数组(f[tm][x][ch])表示第(tm)次操作时,([-B-])中第(1sim x)位中有多少个(ch)字符(这个东西可以预处理)
3、如果说(x>p),那么我们可以将([---A---][-B-][-B-])的答案直接加进去,然后递归处理,因为可以转化成求([---A---])的第(1sim (x-p))位的贡献,所以直接递归查询(tm-1)次操作之后第(x-p)个位置即可
然后至于。。这个(f)怎么预处理。。其实我们只要实现一个能查询到一个位置是什么字符的函数就好了,然后这个的话。。其实就是跟上面一样的嘛qwq不同的是第2中情况我们可以看成查询第一个([-B-])中的位置(两个([-B-])一样的嘛),然后就快乐递归处理就好了(十分意外的是貌似这个是。。自己非常容易忽略的点。。至于为什么我也不是很清楚。。)
所以其实想清楚了超级清晰的==但是。。但是。。但是。。
代码大概长这个样子
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=1e5+10,C=26;
const ll TOP=2e18;//要乘一个2是因为。。查的时候会多查一次操作
char s[110];
ll f[70][110][C],cnt[110][C],K[N];
int n,m,lens;
ll get_len(int tm){return 1LL*lens*(1LL<<tm);}
int get_char(int tm,ll x){
if (x<=lens) return s[x]-'a';
ll mid=get_len(tm-1),p=mid+K[tm];
if (x<=mid) return get_char(tm-1,x);
if (x<=p) return get_char(tm-1,mid-(p-x));
return get_char(tm-1,x-p);
}
int Get_char(ll x){
int tm=0;
while (get_len(tm)<x) ++tm;
return get_char(tm,x);
}
void prework(int n){
for (int i=1;i<=lens;++i)
for (int j=0;j<C;++j)
cnt[i][j]=cnt[i-1][j]+(s[i]-'a'==j);
ll p;
for (int tm=0;get_len(tm)<=TOP&&tm<=n;++tm){
K[tm]%=get_len(tm);
for (int ch=0;ch<C;++ch) f[tm][0][ch]=0;
for (int i=1;i<=K[tm];++i){
p=get_len(tm-1)+i;
for (int ch=0;ch<C;++ch)
f[tm][i][ch]=f[tm][i-1][ch]+(Get_char(p)==ch);
}
}
}
ll solve(int tm,ll x,int ch){
if (tm==0) return cnt[x][ch];
ll mid=get_len(tm-1),p=mid+K[tm];
if (x<=mid) return solve(tm-1,x,ch);
if (x<=p) return (1LL<<tm-1)*cnt[lens][ch]+f[tm][x-mid][ch];
return (1LL<<tm-1)*cnt[lens][ch]+f[tm][K[tm]][ch]+solve(tm-1,x-p,ch);
}
ll calc(ll x,int ch){
if (!x) return 0;
int tm=0;
while (get_len(tm)<x) ++tm;
return solve(tm,x,ch);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
ll l,r,tmp1,tmp2;
char ch;
scanf("%s",s+1); lens=strlen(s+1);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i) scanf("%lld",K+i);
prework(n);
for (int i=1;i<=m;++i){
scanf("%lld%lld %c",&l,&r,&ch);
tmp1=calc(r,ch-'a');
tmp2=calc(l-1,ch-'a');
printf("%lld
",tmp1-tmp2);
}
}