題目鏈接
https://acm.bnu.edu.cn/v3/contest_show.php?cid=8506#problem/A
problem description
As we know, the NTU Final PK contest usually tends to be pretty hard. Many teams got frustrated when participating NTU Final PK contest. So I decide to make the first problem as “easy” as possible. But how to know how easy is a problem? To make our life easier, we just consider how easy is a string. Here, we introduce a sane definition of “easiness”. The easiness of a string is the maximum times of “easy” as a subsequence of it. For example, the easiness of “eeaseyaesasyy” is 2. Since “easyeasy” is a subsequence of it, but “easyeasyeasy” is too easy. How to calculate easiness seems to be very easy. So here is a string s consists of only ‘e’, ‘a’, ‘s’, and ‘y’. Please answer m queries. The i-th query is a interval [li , ri ], and please calculate the easiness of s[li ..ri ].
Input
The first line contains a string s. The second line contains an integer m. Each of following m lines contains two integers li , ri . • 1 ≤ |s| ≤ 105 • 1 ≤ m ≤ 105 • 1 ≤ li ≤ ri ≤ |s| • s consists of only ‘e’, ‘a’, ‘s’, and ‘y’
Output
For each query, please output the easiness of that substring in one line.
Examples
standard input
easy
3
1 4
2 4
1 3
eeaseyaesasyy
4
1 13
2 12
2 10
3 11
standard output
1
0
0
2
2
1
0
題意:給了一個只含有'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], 查詢時,先找到v=p[r] 然後找左邊有效字符個數,最後除以4 就是結果;
代碼如下:
#include <iostream> #include <algorithm> #include <stdio.h> #include <cstring> #include <queue> using namespace std; typedef long long LL; char s[100005]; int a[100005],p[100005]; int anc[100005][21]; int mp[4]; int main() { int m; while(scanf("%s",s+1)!=EOF) { int len=strlen(s+1); for(int i=1;i<=len;i++) { if(s[i]=='e') a[i]=0; else if(s[i]=='a') a[i]=1; else if(s[i]=='s') a[i]=2; else a[i]=3; } memset(mp,0,sizeof(mp)); for(int i=1;i<=len;i++) { int pre=(a[i]-1+4)%4; anc[i][0]=mp[pre]; mp[a[i]]=i; p[i]=mp[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]; } } scanf("%d",&m); while(m--) { int l,r; int sum=1; scanf("%d%d",&l,&r); int v=p[r]; for(int i=20;i>=0;i--) { if(anc[v][i]>=l){ sum+=(1<<i); v=anc[v][i]; } } printf("%d\n",sum/4); } } return 0; }