题目描述
usaco的题目果然都很好呀
算法1
rmq, 预处理
C++ 代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 100010;
int pre[26];
int col[N];
int pl[N], pr[N];
int n, Q;
char str[N];
int rmq[N][17];
void init()
{
for(int i = 0; 1 << i <= n; ++ i)
for(int j = 1; j + (1 << i) - 1 <= n; ++ j)
if(i == 0) rmq[j][i] = col[j];
else rmq[j][i] = min(rmq[j][i - 1], rmq[j + (1 << (i - 1))][i - 1]);
}
int get_min(int l, int r)
{
int k = log(r - l + 1) / log(2);
return min(rmq[l][k], rmq[r - (1 << k) + 1][k]);
}
void get_p()
{
int cnt = 0;
for(int i = 1; i <= n; ++ i)
{
int c = col[i];
if(!pre[c]) ++ cnt;
else if(i > pre[c] + 1 && get_min(pre[c] + 1, i - 1) < c) ++ cnt;
pl[i] = cnt;
pre[c] = i;
}
memset(pre, 0, sizeof pre);
cnt = 0;
for(int i = n; i; -- i)
{
int c = col[i];
if(!pre[c]) ++ cnt;
else if(i < pre[c] - 1 && get_min(i + 1, pre[c] - 1) < c) ++ cnt;
pr[i] = cnt;
pre[c] = i;
}
}
int main()
{
scanf("%d%d", &n, &Q);
scanf("%s", str);
for(int i = 0; str[i]; ++ i) col[i + 1] = str[i] - 'A';
init();
get_p();
while(Q --)
{
int l, r;
scanf("%d%d", &l, &r);
printf("%d\n", pl[l - 1] + pr[r + 1]);
}
return 0;
}