题意分析:
在一个长度为n的只包含b和w的字符串中,给出m个操作,0操作改某位为b或者w中的一个字符,1操作查询区间[L,R]内有多少个wbw
解题思路:
sum[i]代表前到第i个字符为止所拥有的wbw的个数,a[]用来存储线段树结点值,也就是sum[]值。整道题就是线段树区间更新和单点查询。
个人感受:
想到用sum来存储,然后推算更新单点会影响后方所有的点,不知道怎么处理(尼玛,其实就是线段树区间更新啊喂)。然后和队友讨论,知道是线段树就开搞了= =。结果也是蛮坑的。首先区间查询的话,实际上是++L,++R后,查询[L + 1,R]这个区间段的值,因为L + 1, L, L - 1有可能构成wbw但是这个却不属于我们的查询区间[L,R],所以要从L + 1开始。其次,L可以等于R,导致L + 1可能大于R,没注意啊。。。。。唯一值得欣慰的是线段树没写错。。。。。23333
具体代码如下:
#include<algorithm> #include<cctype> #include<cmath> #include<cstdio> #include<cstring> #include<iomanip> #include<iostream> #include<map> #include<queue> #include<set> #include<sstream> #include<stack> #include<string> #define lowbit(x) (x & (-x)) #define root 1, n, 1 #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 #define ll long long #define pr(x) cout << #x << " = " << (x) << '\n'; using namespace std; const int INF = 0x7f7f7f7f; const int MAXN = 5e4 + 111; int sum[MAXN], a[MAXN << 2], add[MAXN << 2]; char s[MAXN]; void build(int l, int r, int rt) { add[rt] = 0; if (l == r) { a[rt] = sum[l]; return; } int m = l + r >> 1; build(lson); build(rson); return; } void push_down(int rt) { if (add[rt] != 0) { add[rt << 1] += add[rt]; add[rt << 1 | 1] += add[rt]; add[rt] = 0; } } void update(int L, int R, int x, int l, int r, int rt) { if (L <= l && r <= R) { add[rt] += x; return; } push_down(rt); int m = l + r >> 1; if (L <= m) update(L, R, x, lson); if (m < R) update(L, R, x, rson); return; } int query(int x, int l, int r, int rt) { if (l == r) { return a[rt] + add[rt]; } push_down(rt); int m = l + r >> 1; if (m < x) return query(x, rson); else return query(x, lson); } int main() { int m, t, n; for (int kase = scanf("%d", &t); kase <= t; ++kase) { printf("Case %d:\n", kase); scanf("%d%d%s", &n, &m, s + 1); sum[0] = sum[1] = sum[2] = 0; for (int i = 3; i <= n; ++i) { sum[i] = sum[i - 1]; if (s[i] == 'w' && s[i - 1] == 'b' && s[i - 2] == 'w') ++sum[i]; } build(root); int op, l, r; char x[2]; while (m --) { scanf("%d%d", &op, &l); if (op == 0) { scanf("%d", &r); ++l, ++r; if (r - l + 1 < 3) printf("0\n"); else printf("%d\n", query(r, root) - query(l + 1, root)); } else { scanf("%s", x); ++l; if (s[l] != x[0]) { if (l >= 3 && s[l] == 'w' && s[l - 1] == 'b' && s[l - 2] == 'w') update(l, n, -1, root); if (l >= 2 && l + 1 <= n && s[l] == 'b' && s[l - 1] == 'w' && s[l + 1] == 'w') update(l + 1, n, -1, root); if (l + 2 <= n && s[l] == 'w' && s[l + 1] == 'b' && s[l + 2] == 'w') update(l + 2, n, -1, root); s[l] = x[0]; if (l >= 3 && s[l] == 'w' && s[l - 1] == 'b' && s[l - 2] == 'w') update(l, n, 1, root); if (l >= 2 && l + 1 <= n && s[l] == 'b' && s[l - 1] == 'w' && s[l + 1] == 'w') update(l + 1, n, 1, root); if (l + 2 <= n && s[l] == 'w' && s[l + 1] == 'b' && s[l + 2] == 'w') update(l + 2, n, 1, root); } } } } return 0; }