【题解参考blog】http://www.cnblogs.com/chen9510/p/5934105.html

【题意】给了一个只含有'e'  'a'  's'  'y'  的字符串然后m次询问,每次询问输入l r 求这个区间含有多少个“easy”序列(每个“easy” 字符之间不需要连在一起)。

【解题方法】倍增法。每个点只记录最靠近它的在它左边的那个字母的位置,比如'e'记录前面的'y','a'记录前面的'e','s'记录前面的'a','y'记录前面的's' 并注意记录距离i最近(左边的y)的y的位置(用p[i]存储)  定义anc[i][j] 表示第i个字符前的第(1<<j)个字符的位置,这个可以用倍增做到 anc[i][j]=anc[anc[i][j-1]][j-1],  查询时,先找到tmp=p[r] 然后找左边有效字符个数,最后除以4 就是结果。注意查询的时候答案初始化为1,因为从y开始查找的。

【代码君】

//
//Created by just_sort 2016/10/5
//Copyright (c) 2016 just_sort.All Rights Reserved
//
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1e5+7;
char str[maxn];
int a[maxn],p[maxn];
int anc[maxn][22];
int main()
{
    while(scanf("%s",str+1)!=EOF)
    {
        int len = strlen(str+1);
        for(int i = 1; i <= len; i++)
        {
            if(str[i] == 'e') a[i] = 0;
            else if(str[i] == 'a') a[i] = 1;
            else if(str[i] == 's') a[i] = 2;
            else{
                a[i] = 3;
            }
        }
        int id[4];
        memset(id,0,sizeof(id));
        for(int i = 1; i <= len; i++)
        {
            int pre = (a[i]+3)%4;
            anc[i][0] = id[pre];
            id[a[i]] = i;
            p[i] = id[3];
        }
        for(int i = 1; i <= 20; i++)
        {
            for(int j = 1; j <= len; j++)
            {
                anc[j][i] = anc[anc[j][i-1]][i-1];
            }
        }
        int q;
        scanf("%d",&q);
        while(q--)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            if(l > r) swap(l,r);
            int ans = 1;
            int tmp = p[r];
            for(int i = 20; i >= 0; i--){
                if(anc[tmp][i] >= l)
                {
                    ans += (1<<i);
                    tmp = anc[tmp][i];
                }
            }
            printf("%d\n",ans/4);
        }
    }
    return 0;
}