疯狂的限制
题目背景:
分析:算是暴力吧······
本来是在做DP来着,然后看到这道题就一起做掉了······做了这道题终于发现,vector是多么有用的东西······我们枚举右端点,那么每次往右移动一个,相当于加入了一个字符,假设当前位置为cur, tot[i]表示i ~ cur所形成的子串满足了多少条件,那么新加进来的s[cur + 1]对tot的影响其实非常小,他影响的就是所有字符为s[cur + 1]的限制的贡献,(c[i] == s[cur + 1]),如果当前位置cur + 1, 是第k个s[cur + 1]出现的位置,那么影响到的贡献位置就是第k - l[i]个s[cur + 1]和第k - l[i] + 1个s[cur + 1]之间。还有第k - r[i] - 1和第k - r[i]个s[cur + 1], 那么我们要做的就是快速找到每一个限制字符为s[cur + 1]的限制,和上面所说的影响到的s[cur + 1]出现的位置,这两者都可以很快的通过vector找到,然后暴力一发,注意边界即可。
注意:
1、关于边界
我们可以预先在存储每一个字符出现位置的vector中预先放入-1,这样就可以很方便的更改开头一段的贡献了
2、关于0
因为可能某些限制的l[i] == 0统计的时候可能会出现问题,所以需要单独进行考虑。
Source:
/*
created by scarlyw
*/
#include <cstdio>
#include <string>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
#include <cctype>
#include <vector>
#include <set>
#include <queue>
const int MAXN = 100000 + 10;
const int ALP = 26;
const int MAXM = 500 + 10;
char c;
char s[MAXN];
int k, len, cnt, ans, l_limit, r_limit;
int q[MAXM][3], tot[MAXN];
long long final_ans;
std::vector<int> query[ALP];
std::vector<int> pos[ALP];
inline void read_in() {
scanf("%s", s), len = strlen(s), cnt = 0;
scanf("%d%d%d", &k, &l_limit, &r_limit);
for (int i = 1; i <= k; ++i) {
static char c[5];
scanf("%s%d%d", c, &q[i][1], &q[i][2]);
q[i][0] = c[0] - 'a', query[q[i][0]].push_back(i);
cnt += (q[i][1] == 0);
}
}
inline void solve() {
for (int i = 0; i < ALP; ++i) pos[i].push_back(-1);
int ans = 0;
for (int i = 0; i < len; ++i) {
int c = s[i] - 'a';
pos[c].push_back(i), tot[i] += cnt;
ans += (tot[i] >= l_limit && tot[i] <= r_limit);
for (int k = query[c].size() - 1; k >= 0; --k) {
int p = query[c][k], size = pos[c].size() - 1;
if (size >= q[p][1] && q[p][1] != 0)
for (int j = pos[c][size - q[p][1]] + 1;
j <= pos[c][size - q[p][1] + 1]; ++j) {
tot[j]++, (tot[j] == l_limit) ? (ans++) :
(tot[j] == r_limit + 1 ? ans-- : 0);
}
if (size > q[p][2])
for (int j = pos[c][size - q[p][2] - 1] + 1;
j <= pos[c][size - q[p][2]]; ++j) {
tot[j]--, (tot[j] == l_limit - 1) ? (ans--) :
(tot[j] == r_limit ? ans++ : 0);
}
}
final_ans += (long long)ans;
}
printf("%lld", final_ans);
}
int main() {
read_in();
solve();
return 0;
}