主要针对” 3 3 3的整倍数下一局不扣分“限制条件找思路。考虑维护三棵线段树,第一颗线段树表示取模为 0 0 0时后对应分数 *** 作,第二三棵类推。
然后只需要进行一个建树和一个单点查询的 *** 作:注意在push_up的时候,合并左右区间的 *** 作时,对右区间需要额外考虑左区间对分数的影响,也就是算出左区间影响后的分数再取对应 *** 作。
另外,再查询时也需要考虑左区间加入后对右区间的影响。
#includeusing namespace std; const int N = 2e5 + 10; int tree[N << 2][3]; char a[N]; struct node{ int v[3]; node(int a, int b, int c){ v[0] = a, v[1] = b, v[2] = c; }}; inline void push_up(int rt){ for(int i = 0; i < 3; i++) tree[rt][i] = tree[rt << 1][i] + tree[rt << 1 | 1][(i + tree[rt << 1][i]) % 3]; } void build(int rt, int l, int r){ if(l == r){ if(a[l] == 'W') tree[rt][0] = tree[rt][1] = tree[rt][2] = 1; else if(a[l] == 'L') tree[rt][0] = 0, tree[rt][1] = tree[rt][2] = -1; else tree[rt][0] = tree[rt][1] = tree[rt][2] = 0; return; } int mid = l + r >> 1; build(rt << 1, l, mid), build(rt << 1 | 1, mid + 1, r); push_up(rt); } node query(int rt, int l, int r, int L, int R){ if(l >= L && r <= R) return node{ tree[rt][0], tree[rt][1], tree[rt][2] }; int mid = l + r >> 1; if(mid >= R) return query(rt << 1, l, mid, L, R); else if(mid < L) return query(rt << 1 | 1, mid + 1, r, L, R); else{ auto ll = query(rt << 1, l, mid, L, R), rr = query(rt << 1 | 1, mid + 1, r, L, R); node res(0, 0, 0); for(int i = 1; i < 3; i++) res.v[i] = ll.v[i] + rr.v[(i + ll.v[i]) % 3]; return res; } } inline void solve(){ int n = 0, q = 0; cin >> n >> q >> a + 1; build(1, 1, n); while(q--){ int l, r, s; cin >> l >> r >> s; cout << query(1, 1, n, l, r).v[s % 3] + s << endl; } } signed main(){ //int t = 0; cin >> t; //while(t--) solve(); solve(); return 0; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)