Submission #1262523

#TimeUsernameProblemLanguageResultExecution timeMemory
1262523M_W_13Modern Machine (JOI23_ho_t5)C++20
100 / 100
865 ms188984 KiB
#include <bits/stdc++.h> using namespace std; #define rep(i, n) for (ll i = 0; i < (n); i++) typedef long long ll; #define st first #define nd second #define pb push_back const ll MAXN = 1 << 17; const ll MAXK = 20; ll maksmale[MAXN][MAXK]; ll minduze[MAXN][MAXK]; ll sumamale[MAXN][MAXK]; ll sumaduze[MAXN][MAXK]; ll gdziep[MAXN]; ll gdziel[MAXN]; ll ilewprawo[MAXN]; ll ilewlewo[MAXN]; struct trojka { ll l, r; ll a; }; vector<trojka> seg[2 * MAXN]; int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); gdziel[0] = -1; gdziep[0] = MAXN - 1; ll n, m; cin >> n >> m; string s; cin >> s; ll t = 0; ll ktp = 0; ll ktl = 0; rep(i, n) { if (s[i] == 'R') { ktp++; t++; } else { ktl++; gdziel[ktl] = i; } ilewlewo[i] = ktl; ilewprawo[i] = ktp; } ktp = 0; for (ll i = n - 1; i >= 0; i--) { if (s[i] == 'R') { ktp++; gdziep[ktp] = i; } } ll lewbaza = 0; while (lewbaza < n && s[lewbaza] == 'R') { lewbaza++; } ll prawbaza = n - 1; while (prawbaza >= 0 && s[prawbaza] == 'B') { prawbaza--; } ll T[m]; ll polow = n/2; rep(i, m) { cin >> T[i]; if (T[i] <= polow) { sumamale[i][0] += T[i]; maksmale[i][0] = T[i]; minduze[i][0] = n + 5; } else { sumaduze[i][0] += (n - T[i]); maksmale[i][0] = -1; minduze[i][0] = T[i]; } ll v = i + MAXN; seg[v].pb({0, T[i] - 1, T[i] + 1}); seg[v].pb({T[i], n, T[i]}); } for (ll k = 1; k < MAXK; k++) { ll ile = (1 << (k - 1)); rep(i, m) { if (i + ile >= m) { sumamale[i][k] = sumamale[i][k - 1]; sumaduze[i][k] = sumaduze[i][k - 1]; maksmale[i][k] = maksmale[i][k - 1]; minduze[i][k] = minduze[i][k - 1]; } else { sumamale[i][k] = sumamale[i][k - 1] + sumamale[i + ile][k - 1]; sumaduze[i][k] = sumaduze[i][k - 1] + sumaduze[i + ile][k - 1]; maksmale[i][k] = max(maksmale[i][k - 1], maksmale[i + ile][k - 1]); minduze[i][k] = min(minduze[i][k - 1], minduze[i + ile][k - 1]); } } } for (ll i = m; i < MAXN; i++) { seg[i + MAXN].push_back({0, n, 0}); } for (ll v = MAXN - 1; v >= 1; v--) { vector<trojka> baza; for (auto troj: seg[2 * v]) { ll l = (troj.l + troj.a) % (n + 1); ll r = (troj.r + troj.a) % (n + 1); if (l > r) { ll kt = n; ll ile = kt - l; baza.pb({troj.l, troj.l + ile, troj.a}); baza.pb({troj.l + ile + 1, troj.r, troj.a}); } else { baza.pb(troj); } } for (auto troj: baza) { ll l = (troj.l + troj.a) % (n + 1); ll r = (troj.r + troj.a) % (n + 1); ll sz = seg[2 * v + 1].size(); ll poc = 0; ll kon = sz; ll odp = sz; while (poc < kon) { ll sr = (poc + kon)/2; if (seg[2 * v + 1][sr].l > l) { kon = sr; } else { poc = sr + 1; odp = sr; } } ll it = odp; while (it < sz && seg[2 * v + 1][it].l <= r) { ll wspl = max(l, seg[2 * v + 1][it].l); ll wspr = min(r, seg[2 * v + 1][it].r); ll jakie = seg[2 * v + 1][it].a; seg[v].pb({troj.l + wspl - l, troj.l + wspr - l, (jakie + troj.a) % (n + 1)}); it++; } } } // for (auto troj: seg[1]) { // cout << troj.l << " " << troj.r << " " << troj.a << '\n'; // } ll z; cin >> z; while (z--) { ll l, r; cin >> l >> r; l--; r--; ll jakiet = 0; ll lew = lewbaza; ll praw = prawbaza; bool czykonc = false; while (lew <= praw) { // cout << "lew = " << lew << " praw = " << praw << " 33" << '\n'; ll liczbawlewo = ilewlewo[praw]; if (lew - 1 >= 0) { liczbawlewo -= ilewlewo[lew - 1]; } ll liczbawprawo = ilewprawo[praw]; if (lew - 1 >= 0) { liczbawprawo -= ilewprawo[lew - 1]; } ll it = l; ll k = MAXK - 1; ll przedwlewo = 0; if (lew > 0) { przedwlewo = ilewlewo[lew - 1]; } ll zaprawo = ilewprawo[n - 1]; if (praw >= 0) { zaprawo -= ilewprawo[praw]; } ll sumamalych = 0; ll sumaduzych = 0; while (k >= 0) { if (((it + (1 << k) - 1) > r) || maksmale[it][k] > lew || minduze[it][k] <= praw + 1 || sumamale[it][k] + sumamalych >= liczbawlewo || sumaduze[it][k] + sumaduzych >= liczbawprawo) { } else if (max(lew, gdziel[sumamale[it][k] + sumamalych + przedwlewo] + 1) >= min(praw, gdziep[sumaduze[it][k] + sumaduzych + zaprawo] - 1)) { } else { sumamalych += sumamale[it][k]; // cout << "it = " << it << " k = " << k << " suma = " << sumamale[it][k] << " sum2 = " << sumaduze[it][k] << '\n'; sumaduzych += sumaduze[it][k]; it += ((1 << k)); } k--; } // cout << "it = " << it << '\n'; // cout << sumamalych << " " << sumaduzych << '\n'; // cout << przedwlewo << " " << zaprawo << '\n'; // cout << gdziel[1] << '\n'; // cout.flush(); if (l < it) { lew = max(lew, gdziel[sumamalych + przedwlewo] + 1); praw = min(praw, gdziep[sumaduzych + zaprawo] - 1); } liczbawlewo = ilewlewo[praw]; if (lew - 1 >= 0) { liczbawlewo -= ilewlewo[lew - 1]; } liczbawprawo = ilewprawo[praw]; if (lew - 1 >= 0) { liczbawprawo -= ilewprawo[lew - 1]; } przedwlewo = 0; if (lew > 0) { przedwlewo = ilewlewo[lew - 1]; } zaprawo = ilewprawo[n - 1]; if (praw >= 0) { zaprawo -= ilewprawo[praw]; } // cout << "lew = " << lew << " praw = " << praw << " it = " << it << " x = " << T[it] << '\n'; if (it <= r) { ll x = T[it]; if (x <= lew) { if (x <= liczbawlewo) { lew = max(lew, gdziel[x + przedwlewo] + 1); } else { jakiet = lew + liczbawprawo; if (x <= jakiet) { jakiet = (jakiet + x) % (n + 1); } else { jakiet = (jakiet + x + 1) % (n + 1); } lew = jakiet; praw = jakiet - 1; } } else if (x <= praw + 1) { x--; ll odbl = 0; ll odbr = 0; odbr += ilewlewo[praw]; odbr -= ilewlewo[x]; odbl = ilewprawo[x - 1]; // cout << odbl << " " << odbr << '\n'; ll poprawo = 0; poprawo += ilewprawo[n - 1]; if (x - 1 >= 0) { poprawo -= ilewprawo[x - 1]; } if (lew - 1 >= 0) { odbl -= ilewprawo[lew - 1]; } if (odbl < odbr) { ll now = gdziel[odbl + 1 + ilewlewo[x]] + 1; x = lew; lew = now; liczbawlewo = ilewlewo[praw]; if (lew - 1 >= 0) { liczbawlewo -= ilewlewo[lew - 1]; } liczbawprawo = ilewprawo[praw]; if (lew - 1 >= 0) { liczbawprawo -= ilewprawo[lew - 1]; } przedwlewo = 0; if (lew > 0) { przedwlewo = ilewlewo[lew - 1]; } zaprawo = ilewprawo[n - 1]; if (praw >= 0) { zaprawo -= ilewprawo[praw]; } if (x <= liczbawlewo) { lew = max(lew, gdziel[x + przedwlewo] + 1); } else { jakiet = lew + liczbawprawo; if (x <= jakiet) { jakiet = (jakiet + x) % (n + 1); } else { jakiet = (jakiet + x + 1) % (n + 1); } lew = jakiet; praw = jakiet - 1; } } else { ll now = gdziep[odbr + poprawo] - 1; x = praw + 1; praw = now; liczbawlewo = ilewlewo[praw]; if (lew - 1 >= 0) { liczbawlewo -= ilewlewo[lew - 1]; } liczbawprawo = ilewprawo[praw]; if (lew - 1 >= 0) { liczbawprawo -= ilewprawo[lew - 1]; } przedwlewo = 0; if (lew > 0) { przedwlewo = ilewlewo[lew - 1]; } zaprawo = ilewprawo[n - 1]; if (praw >= 0) { zaprawo -= ilewprawo[praw]; } if (n - x <= liczbawprawo) { praw = min(praw, gdziep[n - x + zaprawo] - 1); } else { jakiet = lew + liczbawprawo; if (x <= jakiet) { jakiet = (jakiet + x) % (n + 1); } else { jakiet = (jakiet + x + 1) % (n + 1); } lew = jakiet; praw = jakiet - 1; } } } else { if (n - x <= liczbawprawo) { praw = min(praw, gdziep[n - x + zaprawo] - 1); } else { jakiet = lew + liczbawprawo; if (x <= jakiet) { jakiet = (jakiet + x) % (n + 1); } else { jakiet = (jakiet + x + 1) % (n + 1); } lew = jakiet; praw = jakiet - 1; } } } l = it + 1; if (l > r) { czykonc = true; break; } } // cout << "lew = " << lew << " praw = " << praw << '\n'; // cout << "l = " << l << " r = " << r << '\n'; // cout.flush(); if (czykonc) { ll liczbawlewo = ilewlewo[praw]; if (lew - 1 >= 0) { liczbawlewo -= ilewlewo[lew - 1]; } ll liczbawprawo = ilewprawo[praw]; if (lew - 1 >= 0) { liczbawprawo -= ilewprawo[lew - 1]; } cout << lew + liczbawprawo << '\n'; continue; } l += MAXN; r += MAXN; deque<ll> dq; deque<ll> dq2; ll gdzie = lew; while (l < r) { if (l % 2 == 1) { dq.push_back(l); l++; } if (r % 2 == 0) { dq2.push_front(r); r--; } l /= 2; r /= 2; } if (l == r) { dq.push_back(l); } queue<ll> q; while (!dq.empty()) { q.push(dq.front()); dq.pop_front(); } while (!dq2.empty()) { q.push({dq2.front()});; dq2.pop_front(); } while (!q.empty()) { ll v = q.front(); q.pop(); ll sz = seg[v].size(); // cout << "sz = " << sz << '\n'; ll poc = 0; ll kon = sz; ll odp = sz; while (poc < kon) { ll sr = (poc + kon)/2; if (seg[v][sr].l > gdzie) { kon = sr; } else { poc = sr + 1; odp = sr; } } // cout << "gdzie = " << gdzie << '\n'; // cout << "odp = " << odp << '\n'; gdzie += seg[v][odp].a; gdzie %= (n + 1); } cout << gdzie << '\n'; } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...