题目链接:
[UVA 11402]Ahoy, Pirates![线段树]
题意分析:
给出只包含01的字符串,F操作把区间[a,b]的字符变成1,E操作把区间的字符变成0,I操作把区间中的1变0,0变1,Q操作查询区间中的1的个数。
解题思路:
使用线段树区间更新与查询解决本题。特设一个lazy数组,但lazy为1代表这个区间都是1,0代表这个区间都是0,-1代表这个区间成分不纯。
个人感受:
lazy数组一直没有处理好,之前想着怎么处理这三个状态之间的关系,更新写到后期全都乱套了。亮点就是-1代表不纯的区间,让纯的子区间来回答查询。
具体代码如下:
#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 = 1e6 + 4e4;
int sum[MAXN << 2], lazy[MAXN << 2], n;
string s;
void push_down(int l, int r, int rt) {
if (lazy[rt] != -1) {
int m = l + r >> 1;
lazy[rt << 1] = lazy[rt << 1 | 1] = lazy[rt];
sum[rt << 1] = (m - l + 1) * lazy[rt];
sum[rt << 1 | 1] = (r - m) * lazy[rt];
lazy[rt] = -1;
}
}
void build(int l, int r, int rt) {
if (l == r) {
lazy[rt] = sum[rt] = s[l] - '0';
return;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
if (sum[rt] == r - l + 1)
lazy[rt] = 1;
else if (sum[rt] == 0)
lazy[rt] = 0;
else
lazy[rt] = -1;
}
void update(int L, int R, int l, int r, int rt, int flag) {
if (L <= l && r <= R && !(flag == -1 && lazy[rt] == -1)) {
if (flag == -1) {
lazy[rt] = 1 - lazy[rt];
sum[rt] = (r - l + 1) * lazy[rt];
}
else {
lazy[rt] = flag;
sum[rt] = (r - l + 1) * lazy[rt];
}
return;
}
push_down(l, r, rt);
int m = l + r >> 1;
if (L <= m) update(L, R, lson, flag);
if (m < R) update(L, R, rson, flag);
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
int query(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R)
return sum[rt];
else if (r < L || R < l)
return 0;
push_down(l, r, rt);
int m = l + r >> 1;
return query(L, R, lson) + query(L, R, rson);
}
int main()
{
#ifdef LOCAL
freopen("C:\\Users\\apple\\Desktop\\in.txt", "r", stdin);
#endif
ios::sync_with_stdio(0);
int t; cin >> t;
for (int kase = 1; kase <= t; ++kase) {
s.clear();
s += '0';
int m, time;
string tmp;
cin >> m;
for (int i = 0; i < m; ++i) {
cin >> time >> tmp;
for (int j = 0; j < time; ++j) {
s += tmp;
}
}
n = s.length() - 1;
build(root);
char op;
int q, a, b; cin >> q;
cout << "Case " << kase << ":\n";
int cnt = 0;
while (q --) {
cin >> op >> a >> b;
++a, ++b;
//cout << op << ' ' << a << ' ' << b << endl;
if (op == 'F') update(a, b, root, 1);
else if (op == 'E') update(a, b, root, 0);
else if (op == 'I') update(a, b, root, -1);
else cout << 'Q' << ++cnt << ": " << query(a, b, root) << '\n';
}
}
return 0;
}