#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define ull unsigned long long
#define ff first
#define ss second
#define pii pair<int,int>
#define pll pair<long long, long long>
#define vi vector<int>
#define vl vector<long long>
#define pb push_back
#define rep(i, b) for(int i = 0; i < (b); ++i)
#define rep2(i,a,b) for(int i = a; i <= (b); ++i)
#define rep3(i,a,b,c) for(int i = a; i <= (b); i+=c)
#define count_bits(x) __builtin_popcountll((x))
#define all(x) (x).begin(),(x).end()
#define siz(x) (int)(x).size()
#define forall(it,x) for(auto& it:(x))
using namespace std;
//mt19937 mt;void random_start(){mt.seed(chrono::time_point_cast<chrono::milliseconds>(chrono::high_resolution_clock::now()).time_since_epoch().count());}
//ll los(ll a, ll b) {return a + (mt() % (b-a+1));}
const int INF = 1e9+50;
const ll INF_L = 1e18+40;
const ll MOD = 1e9+7;
struct query
{
int l,r,cur_pref,cur_suf,ind;
bool operator<(const query& other) const
{
return cur_pref < other.cur_pref;
}
};
int n,m;
string s;
struct seg
{
int l,r,k;
bool operator<(const seg& other) const
{
if(l != other.l) return l < other.l;
return r < other.r;
}
};
struct node
{
vector<seg> segs;
node()
{
segs.pb({0,n,0});
}
void def()
{
segs = {{0,n,0}};
}
void default_a(int a)
{
segs = {};
if(a*2 < n)
{
segs.pb({0,a-1,a+1});
}
else
{
if(n - (a+1) >= 0) segs.pb({0,n-(a+1),a+1});
segs.pb({n-(a+1)+1,a-1,0});
}
int s = (a+a) % (n+1);
if(s + (n - a) <= n)
{
segs.pb({a,n,s});
}
else
{
segs.pb({a,a+n-s,s});
segs.pb({a+n-s+1,n,0});
}
sort(all(segs));
}
node operator+(const node& other)
{
node res;
res.segs = {};
forall(it,segs)
{
seg w = {it.k,(int)1e9,-1};
auto iter = lower_bound(other.segs.begin(),other.segs.end(), w);
iter--;
int cur = it.k;
int cur_poz = it.l;
int r = it.k + (it.r - it.l);
while(cur <= r)
{
if((*iter).r >= r)
{
res.segs.pb({cur_poz,it.r,(*iter).k + cur - (*iter).l});
break;
}
else
{
int d = (*iter).r - cur;
res.segs.pb({cur_poz,cur_poz + d,(*iter).k + cur - (*iter).l});
cur = (*iter).r+1;
cur_poz += d+1;
iter++;
}
}
}
sort(all(res.segs));
return res;
}
int get_val(int k)
{
auto it = lower_bound(segs.begin(),segs.end(),(seg){k,(int)1e9,-1});
it--;
return (*it).k + (k - (*it).l);
}
};
const int tree_siz = 1024*256-1;
node drzewo[tree_siz];
int get_pref(int akt, int p1, int p2, int s1, int s2, int cur)
{
if(p2 < s1 || p1 > s2) return cur;
if(p1 >= s1 && p2 <= s2)
{
return drzewo[akt-1].get_val(cur);
}
cur = get_pref(akt*2,p1,(p1+p2)/2,s1,s2,cur);
cur = get_pref(akt*2+1,(p1+p2)/2+1,p2,s1,s2,cur);
return cur;
}
void build_tree(vi& a)
{
m++;
rep(i,m)
{
drzewo[tree_siz/2+i].default_a(a[i]);
}
rep2(i,tree_siz/2+m,tree_siz-1) drzewo[i].def();
for(int i = tree_siz/2-1; i >= 0; i--)
{
drzewo[i] = drzewo[i*2+1] + drzewo[i*2+2];
}
m--;
}
int prev_L[120'002];
int nxt_R[120'002];
int prefL[120'002];
int prefR[120'002];
int ind[120'002];
int ind_to_poz_L[120'002];
int ind_to_poz_R[120'002];
int arr[120'002];
int query_ans[120'002];
int first_mid[120'002];
int nxt_pref[120'002];
int nxt_suf[120'002];
vi A;
pii nxt_state(int cur_pref, int cur_suf, int v)
{
int R_cnt;
int L_cnt;
if(v <= cur_pref)
{
R_cnt = v-1;
L_cnt = cur_suf + prefL[n-cur_suf] - prefL[cur_pref];
}
else if(v >= n-cur_suf+1)
{
R_cnt = cur_pref + prefR[n-cur_suf] - prefR[cur_pref];
L_cnt = n-v;
}
else
{
R_cnt = cur_pref + prefR[v-1] - prefR[cur_pref];
L_cnt = cur_suf + prefL[n-cur_suf] - prefL[v];
}
if(R_cnt >= L_cnt)
{
swap(R_cnt,L_cnt);
int R2 = 0;
if(v > cur_pref)
{
R2 = prefR[min(n-cur_suf,v-1)] - prefR[cur_pref];
}
if(R2 >= R_cnt)
{
if(R_cnt != 0) return {cur_pref,n-ind_to_poz_R[ind[nxt_R[min(n-cur_suf+1,v)]] + R_cnt]+1};
return {min(cur_pref,v-1),max(cur_suf,n-v+1)};
}
else
{
return {n-(n-(min(v-1,cur_pref) - (R_cnt-R2)+1)+1),n-(min(v-1,cur_pref) - (R_cnt-R2)+1)+1};
}
}
else
{
swap(R_cnt,L_cnt);
int L2 = 0;
if(v <= n-cur_suf)
{
L2 = prefL[n-cur_suf]-prefL[max(cur_pref,v)];
}
L_cnt++;
if(L2 >= L_cnt)
{
if(L_cnt != 0) return {ind_to_poz_L[ind[prev_L[max(v,cur_pref)]]+L_cnt],cur_suf};
return {max(cur_pref,v),min(cur_suf,n-v)};
}
else
{
return {max(v+1,n-cur_suf+1)+(L_cnt-L2-1),n-(max(v+1,n-cur_suf+1)+(L_cnt-L2-1))};
}
}
}
int main()
{
ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
//random_start();
cin >> n >> m >> s;
rep2(i,1,n)
{
arr[i] = 1;
if(s[i-1] == 'B') arr[i] = -1;
}
int cnt = 1;
prev_L[0] = 0;
ind[0] = 0;
rep2(i,1,n)
{
prev_L[i] = prev_L[i-1];
if(arr[i] == -1)
{
prev_L[i] = i;
ind[i] = cnt++;
ind_to_poz_L[ind[i]] = i;
}
}
cnt = 0;
nxt_R[n+1] = n+1;
ind[n+1] = -1;
for(int i = n; i >= 1; i--)
{
nxt_R[i] = nxt_R[i+1];
if(arr[i] == 1)
{
nxt_R[i] = i;
ind[i] = cnt++;
ind_to_poz_R[ind[i]] = i;
}
}
int start_pref = 0;
int start_suf = 0;
rep2(i,1,n)
{
if(arr[i] == 1) start_pref++;
else break;
}
for(int i = n; i >= 1; i--)
{
if(arr[i] == -1) start_suf++;
else break;
}
rep2(i,1,n)
{
prefL[i] = prefL[i-1];
prefR[i] = prefR[i-1];
if(arr[i] == -1) prefL[i]++;
else prefR[i]++;
}
A.resize(m+1,1);
rep2(i,1,m) cin >> A[i];
build_tree(A);
ind_to_poz_L[prefL[n]+1] = n;
ind_to_poz_R[prefR[n]] = 0;
int q;
cin >> q;
vector<query> queries;
rep(i,q)
{
query_ans[i] = -1;
int l,r;
cin >> l >> r;
if(start_pref + start_suf == n)
{
query_ans[i] = get_pref(1,0,tree_siz/2,l,r,start_pref);
}
else
{
queries.pb({l,r,start_pref,start_suf,i});
}
}
vector<query> new_queries;
int iter_cnt = 0;
while(!queries.empty())
{
iter_cnt++;
if(iter_cnt >= 40)
{
int a = 5;
int b = a-5;
cout << a/b << "\n";
}
sort(all(queries));
set<int> ok_poz;
set<pii> sort_poz;
rep2(i,1,m) ok_poz.insert(i);
rep2(i,1,m) sort_poz.insert({A[i],i});
forall(it,queries)
{
int cur_pref = it.cur_pref;
int cur_suf = it.cur_suf;
int cur_poz = it.l;
while(siz(ok_poz) > 0 && (*sort_poz.begin()).ff <= cur_pref)
{
int v = (*sort_poz.begin()).ss;
ok_poz.erase(ok_poz.find(v));
sort_poz.erase(sort_poz.begin());
}
int nxt_poz = it.r+1;
if(siz(ok_poz) > 0)
{
auto iter = ok_poz.lower_bound(it.l);
if(iter != ok_poz.end() && *iter <= it.r)
{
nxt_poz = *iter;
}
}
first_mid[it.ind] = nxt_poz;
}
forall(it,queries)
{
ll add = 0;
rep2(i,it.l,first_mid[it.ind]-1)
{
if(A[i] <= it.cur_pref) add += A[i];
}
nxt_pref[it.ind] = max(it.cur_pref,ind_to_poz_L[min((ll)prefL[n]+1,ind[prev_L[it.cur_pref]]+add)]);
}
forall(it,queries)
{
ll add = 0;
rep2(i,it.l,first_mid[it.ind]-1)
{
if(A[i] > n-it.cur_suf) add += n-A[i];
}
if(ind[nxt_R[n-it.cur_suf+1]]+add != -1) nxt_suf[it.ind] = max(it.cur_suf,1+n-ind_to_poz_R[min((ll)prefR[n],ind[nxt_R[n-it.cur_suf+1]]+add)]);
else nxt_suf[it.ind] = it.cur_suf;
int cur_suf = it.cur_suf;
int cur_pref = it.cur_pref;
if(nxt_pref[it.ind] + nxt_suf[it.ind] >= n)
{
int p = it.l;
while(cur_pref + cur_suf < n)
{
pii w = nxt_state(cur_pref,cur_suf,A[p]);
p++;
cur_pref = w.ff;
cur_suf = w.ss;
}
if(p != it.r+1)
{
query_ans[it.ind] = get_pref(1,0,tree_siz/2,p,it.r,cur_pref);
}
else
{
query_ans[it.ind] = cur_pref;
}
}
else
{
cur_pref = nxt_pref[it.ind];
cur_suf = nxt_suf[it.ind];
if(first_mid[it.ind] <= it.r)
{
pii w = nxt_state(cur_pref,cur_suf,A[first_mid[it.ind]]);
if(first_mid[it.ind] != it.r)
{
if(w.ff + w.ss != n)
{
new_queries.pb({first_mid[it.ind]+1,it.r,w.ff,w.ss,it.ind});
}
else
{
query_ans[it.ind] = get_pref(1,0,tree_siz/2,first_mid[it.ind]+1,it.r,w.ff);
}
}
else
{
query_ans[it.ind] = w.ff + prefR[n-w.ss] - prefR[w.ff];
}
}
else
{
query_ans[it.ind] = cur_pref + prefR[n-cur_suf] - prefR[cur_pref];
}
}
}
queries = new_queries;
new_queries = {};
}
rep(i,q) cout << query_ans[i] << "\n";
}
# | 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... |