CJB的大作 - 乱搞

题目大意:一开始给你一个字符串s,n次操作每次把s的后ai个字符放到前面来拼在原串后面,也就是每次长度倍增。操作完后q组询问l到r区间字符c出现了几次。s和k不超过100,n和q不超过1e5,l和r不超过1e18。
题解:直接搞一个solve(k,n,c)表示操作k次前n个字符c出现的次数,那么根据n和|s|*2^k(+a[k])的大小关系直接计算即可,记忆化ans(k,n,c)表示第k次操作当n<=a[k]的时候字符c出现的次数才能够保证复杂度。
事实上还可以可持久化treap,这样复杂度就不是很依赖于ai了。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<assert.h>
#define gc getchar()
#define MXL 60
#define N 100010
#define INF 1000000000000000000ll
#define lint long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
int a[N],c[26][110],m;bool ask[26][MXL+10][110];
lint mi[MXL+10],Ans[26][MXL+10][110];char s[110];
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
inline lint inln()
{
    lint x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
inline int gtc(int x=0) { while((x=gc)<'a'||x>'z');return x-'a'; }
lint solve(lint n,int L,int ch);
inline lint calc(int k,lint p,int ch)
{
    if(ask[ch][k][p]) return Ans[ch][k][p];ask[ch][k][p]=1;
    return Ans[ch][k][p]=solve(m*mi[k-1]-a[k]+p,k-1,ch)-solve(m*mi[k-1]-a[k],k-1,ch);
}
inline lint solve(lint n,int L,int ch)
{
    if(!n) return 0;if(!L) return c[ch][n];
    if(n<=m*mi[L-1]) return solve(n,L-1,ch);
    lint ans=c[ch][m]*mi[L-1];n-=m*mi[L-1];
    if(n<=a[L]) return ans+calc(L,n,ch);
    return ans+calc(L,a[L],ch)+solve(n-a[L],L-1,ch);
}
int main()
{
    scanf("%s",s+1);int n=inn(),q=inn();
    rep(i,(int)(mi[0]=1),MXL) mi[i]=mi[i-1]*2;
    m=(int)strlen(s+1);lint k=m;int L=0;
    for(int i=1;i<=n;i++) a[i]=inn();
    while(k<=INF&&L<n) k<<=1,L++;
    for(int i=1;i<=L;i++) a[i]%=(mi[i-1]*m);
    rep(i,1,m) c[s[i]-'a'][i]++;
    rep(i,0,25) rep(j,1,m) c[i][j]+=c[i][j-1];
    for(int i=1;i<=q;i++)
    {
        lint l=inln(),r=inln();int ch=gtc();
        if(!c[ch][m]) { printf("0\n");continue; }
        printf("%lld\n",solve(r,L,ch)-solve(l-1,L,ch));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/82155096