热爱足球(仅限游戏)的炸鸡块君最近购买了FIFA22,并且沉迷于FIFA22的Rivals排位上分。 在该排位系统中,每局游戏可能有胜利(用W表示)、失败(用L表示)、平局(用D表示)三种结果,胜利将使得排位分加一、失败使排位分减一、平局使排位分不变。特别地,该排位系统有着存档点机制,其可以简化的描述为:若你当前的排位分是3的整倍数(包括0倍),则若下一局游戏失败,你的排位分将不变(而不是减一)。 现在,给定一个游戏结果字符串和若干次询问,你需要回答这些询问。 每次询问格式为(l,r,s),询问若你初始有ss分,按从左到右的顺序经历了[l,r]这一子串的游戏结果后,最终分数是多少。
输入样例
10 7
WLDLWWLLLD
2 6 0
2 6 1
2 6 2
2 6 9
1 7 0
7 10 10
10 10 100
输出样例
2
2
2
11
1
9
100
首先这种2e5的区间查询很容易就想到线段树了,想了一会果然能解。因为题意要求能整除3的时候负不扣分,我们可以分情况讨论进而用线段树维护区间对答案的总贡献,我们设c[i]表示初始值%3后为i的时候选择这一区间后答案的增加量。那初始化很简单对吧这三种状态赢贡献都是1,平都是0,负的话只有0的时候是0其余都是-1
if (s[l] == 'W') { tr[u].c[0] = 1; tr[u].c[1] = 1; tr[u].c[2] = 1; } else if (s[l] == 'L') { tr[u].c[0] = 0; tr[u].c[1] = -1; tr[u].c[2] = -1; } else { tr[u].c[0] = 0; tr[u].c[1] = 0; tr[u].c[2] = 0; }
然后考虑up操作,我们和上面一样分情况讨论,[l,r]区间初始为i的贡献=左区间为i的贡献+右区间初始值为(i+右区间)%3的贡献。
void pushup(int u) { for (int i = 0; i < 3; i++) { tr[u].c[i] = max(tr[u << 1].c[i] + tr[u << 1 | 1].c[(i + tr[u << 1].c[i])%3], -i); } }
至此此题结束。
/*made in dirt & sand */ #include <bits/stdc++.h> #define endl '\n' #define bug(a) cout << a << endl #define bug2(a, b) cout << (a) << ' ' << (b) << endl #define bug3(a, b, c) cout << (a) << ' ' << (b) << ' ' << (c) << endl #define pb push_back //#define int long long #define x first #define y second #define pii pair<int, int> using namespace std; typedef long long ll; const int N = 2e5 + 10; int i, j, n, m, x,y; int a[N]; char s[N]; struct node { int l, r; int c[3]; } tr[N<<2]; void pushup(int u) { for (int i = 0; i < 3; i++) { tr[u].c[i] = max(tr[u << 1].c[i] + tr[u << 1 | 1].c[(i + tr[u << 1].c[i])%3], -i); } } void build(int u, int l, int r) { tr[u] = {l, r}; if (l == r) { if (s[l] == 'W') { tr[u].c[0] = 1; tr[u].c[1] = 1; tr[u].c[2] = 1; } else if (s[l] == 'L') { tr[u].c[0] = 0; tr[u].c[1] = -1; tr[u].c[2] = -1; } else { tr[u].c[0] = 0; tr[u].c[1] = 0; tr[u].c[2] = 0; } } else { tr[u] = {l, r}; int mid = l + r >> 1; build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r); pushup(u); } } ll query(int u, int l, int r, int q) { if (tr[u].l >= l && tr[u].r <= r) { return tr[u].c[q]; } int mid = tr[u].l + tr[u].r >> 1; ll sum = 0; if (l <= mid) sum = query(u << 1, l, min(mid, r), q); if (r > mid) sum += query(u << 1 | 1, max(mid + 1, l), r, (q + sum) % 3); return sum; } signed main() { // freopen("black.in","r",stdin); //std::ios::sync_with_stdio(false); //cin.tie(0); int T = 0; cin >> n >> m; cin >> (s + 1); build(1, 1, n); while (m--) { int z; cin >> x >> y >> z; cout << z + query(1, x, y, z % 3) << endl; ; } }