This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mx = 1.2e5 + 5;
const int magic = 400;
//const int magic = 3;
namespace rmq {
struct segtree {
segtree* lc = 0, * rc = 0;
int l, r;
int v = numeric_limits<int>::max();
segtree* getmem();
segtree() : segtree(-1, -1) {};
segtree(int l, int r) : l(l), r(r) {
if (l == r)return;
int m = (l + r) / 2;
lc = getmem(); *lc = segtree(l, m);
rc = getmem(); *rc = segtree(m + 1, r);
};
segtree* upd(int qi, int qv) {
segtree* tr = getmem(); *tr = *this;
if (qi < l || qi > r) return tr;
if (l == r) { tr->v = qv; return tr; }
tr->lc = lc->upd(qi, qv); tr->rc = rc->upd(qi, qv);
tr->v = min(tr->lc->v, tr->rc->v);
return tr;
}
int q(int ql, int qr) {
if (ql > qr)return numeric_limits<int>::max();
if (ql > r || qr < l) return numeric_limits<int>::max();
if (ql <= l && qr >= r) return v;
return min(lc->q(ql, qr), rc->q(ql, qr));
}
}mem[mx * 40]; int memsz = 0;// surely enogh?
segtree* segtree::getmem() { return &mem[memsz++]; }
}
namespace rsq {
struct segtree {
segtree* lc = 0, * rc = 0;
int l, r;
int v = 0;
segtree* getmem();
segtree() : segtree(-1, -1) {};
segtree(int l, int r) : l(l), r(r) {
if (l == r)return;
int m = (l + r) / 2;
lc = getmem(); *lc = segtree(l, m);
rc = getmem(); *rc = segtree(m + 1, r);
};
segtree* upd(int qi, int qv) {
segtree* tr = getmem(); *tr = *this;
if (qi < l || qi > r) return tr;
if (l == r) { tr->v += qv; return tr; }
tr->lc = lc->upd(qi, qv); tr->rc = rc->upd(qi, qv);
tr->v = tr->lc->v + tr->rc->v;
return tr;
}
int q(int ql, int qr) {
if (ql > qr) return 0;
if (ql > r || qr < l) return 0;
if (ql <= l && qr >= r) return v;
return lc->q(ql, qr) + rc->q(ql, qr);
}
}mem[mx * 80]; int memsz = 0;// surely enogh?
segtree* segtree::getmem() { return &mem[memsz++]; }
}
struct bit {
vector<int> b, a;
vector<pair<int, int>> us;
bit(int n) : b(n + 1, 0), a(n + 1, 0) {};
int q(int i) { int v = 0; for (i++; i > 0; i -= i & -i) v += b[i]; return v; }
void u(int i, int v) { us.push_back({ i, v });if (i < a.size()) a[i] += v; for (i++; i < b.size(); i += i & -i) b[i] += v; }
void u(int l, int r, int v) { if (l > r) return; u(l, v); u(r + 1, -v); }
};
int holy[mx / magic][mx];
int32_t main() {
cin.tie(0)->sync_with_stdio(0);
int n, m; cin >> n >> m;
string c; cin >> c;
vector<int> a(m); for (auto& x : a) { cin >> x; x--; }
vector<vector<int>> a2(n + 1);
for (int i = 0; i < m; i++) a2[a[i]].push_back(i);
vector<int> ls, rs;
ls.push_back(-1); rs.push_back(n);
for (int i = 0; i < n; i++) if (c[i] == 'B') ls.push_back(i);
for (int i = n - 1; i >= 0; i--) if (c[i] == 'R') rs.push_back(i);
vector<int> pre(n, 0);
for (int i = 0; i < n; i++) {
if (i) pre[i] = pre[i - 1];
pre[i] += c[i] == 'R';
}
auto sm = [&](int l, int r) {
if (l > r) return 0LL;
if (l > n) l = n;
if (r > n - 1) r = n - 1;
if (r < 0) return 0LL;
if (l <= 0) return pre[r];
return pre[r] - pre[l - 1];
}; //very necessary yk
rmq::segtree* tmp = new rmq::segtree(0, n - 1);
vector<rmq::segtree*> ac(m, 0);
for (int i = m - 1; i >= 0; i--) {
ac[i] = tmp = tmp->upd(a[i], i);
}
rsq::segtree* tmp2 = new rsq::segtree(0, m - 1);
vector<rsq::segtree*> ac2(n + 1, 0);
for (int i = 0; i <= n; i++) {
for (auto& x : a2[i]) tmp2 = tmp2->upd(x, i + 1);
ac2[i] = tmp2;
}
rsq::segtree* tmp3 = new rsq::segtree(0, m - 1);
vector<rsq::segtree*> ac3(n + 1, 0);
for (int i = n; i >= 0; i--) {
for (auto& x : a2[i]) {
tmp3 = tmp3->upd(x, n - 1 - i);
}
ac3[i] = tmp3;
}
bit die(n + 1);
for (int i = 0; i <= n; i++) die.u(i, i, i);
die.us.clear();
for (int j = 0; j + magic <= m; j += magic) {
int k = j / magic;
for (int x = j; x < j + magic; x++) {
int cur = 0;
while (cur <= n) {
int i = die.q(cur) / (n + 1);
int l = cur - 1, r = n + 1;
while (r - l > 1) {
int m = l + (r - l) / 2;
if (die.q(m) / (n + 1) == i) l = m;
else r = m;
}
//[cur, l] is bound
int l2 = cur - 1, r2 = l + 1;
while (r2 - l2 > 1) {
int m = l2 + (r2 - l2) / 2;
if (die.q(m) % (n + 1) <= a[x]) l2 = m;
else r2 = m;
}
//r is bound
die.u(cur, l2, 1);
cur = l + 1;
}
die.u(0, n, a[x] + 1);
}
int ps = 0;
for (int i = 0; i <= n; i++) {
ps += die.a[i];
holy[k][i] = ps % (n + 1);
}
for (auto& x : die.us)die.u(x.first, -x.second);
die.us.clear();
}
int q; cin >> q;
while (q--) {
int l, r; cin >> l >> r; l--;r--;
//solve
int li = -1, ri = n;
int cur = l;
auto qcnt = [&](int l, int r) {
int res = 0;
if (l > r) return 0LL;
if (r <= li) return r - l + 1;
if (l >= ri) return 0LL;
if (l <= li) {
res += li - l + 1;
l = li + 1;
}
if (r >= ri) r = ri - 1;
return res + sm(l, r);
//LMAO
};
auto qcnt2 = [&](int l, int r) {
if (l > r) return 0LL;
return (r - l + 1) - qcnt(l, r);};
auto thing = [&](int t) { // should work for everything?
int a = qcnt(0, t - 1) * 2 + 1;
int b = qcnt2(t + 1, n - 1) * 2;
if (a > b) {
int ll = 0 - 1, rr = t + 1;
while (rr - ll > 1) {
int m = ll + (rr - ll) / 2;
if (qcnt(m, t - 1) * 2 + 1 >= b)ll = m;
else rr = m;
}
ri = min(ri, ll);
if (li >= ri) li = ri - 1;
} else {
int ll = t, rr = n;
while (rr - ll > 1) {
int m = ll + (rr - ll) / 2;
if (qcnt2(t + 1, m) * 2 >= a)rr = m;
else ll = m;
}
li = rr;
if (ri <= li) ri = li + 1;
}
};
auto test = [&](int t) -> bool {
int v1 = li == -1 ? 0 : ac2[li]->q(cur, t);
int v2 = ri == n ? 0 : ac3[ri]->q(cur, t);
int tmp1 = prev(upper_bound(ls.begin(), ls.end(), li)) - ls.begin();
int tmp2 = prev(upper_bound(rs.begin(), rs.end(), ri, greater<int>())) - rs.begin();
if (tmp1 + v1 >= ls.size()) return false;
if (tmp2 + v2 >= rs.size()) return false;
int nl = v1 ? ls[tmp1 + v1] : li;
int nr = v2 ? rs[tmp2 + v2] : ri;
if (nl >= nr) return false;
li = nl; ri = nr;
cur = t + 1;
return true;
};
while (cur <= r) {
int t = min(ac[cur]->q(li + 1, ri - 1), r + 1);
//do the thing?
if (!test(t - 1)) break;
if (cur <= r)thing(a[cur++]);
}
if (cur <= r && li + 1 != ri) {
int t = min(ac[cur]->q(li + 1, ri - 1), r + 1);
for (int i = 18; i >= 0; i--) {
if (cur + (1 << i) <= t - 1) test(cur + (1 << i));
}
}
for (int i = 0; i < 2; i++) if (cur <= r) thing(a[cur++]);
int nxt = (cur / magic + 1) * magic;
while (cur <= r) {
if (cur == nxt && cur + magic <= r + 1) {
ri = holy[cur / magic][ri];
li = ri - 1;
cur += magic;
nxt += magic;
} else {
if (a[cur] >= ri) ri++;
ri += a[cur] + 1;
while (ri >= n + 1) ri -= (n + 1);
li = ri - 1;
cur++;
}
}
cout << qcnt(0, n - 1) << endl;
}
}
Compilation message (stderr)
Main.cpp: In member function 'void bit::u(long long int, long long int)':
Main.cpp:77:57: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
77 | void u(int i, int v) { us.push_back({ i, v });if (i < a.size()) a[i] += v; for (i++; i < b.size(); i += i & -i) b[i] += v; }
| ~~^~~~~~~~~~
Main.cpp:77:92: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
77 | void u(int i, int v) { us.push_back({ i, v });if (i < a.size()) a[i] += v; for (i++; i < b.size(); i += i & -i) b[i] += v; }
| ~~^~~~~~~~~~
Main.cpp: In lambda function:
Main.cpp:224:27: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
224 | if (tmp1 + v1 >= ls.size()) return false;
| ~~~~~~~~~~^~~~~~~~~~~~
Main.cpp:225:27: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
225 | if (tmp2 + v2 >= rs.size()) return false;
| ~~~~~~~~~~^~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |