Submission #727425

#TimeUsernameProblemLanguageResultExecution timeMemory
727425model_codeModern Machine (JOI23_ho_t5)C++17
100 / 100
1263 ms245456 KiB
#include <iostream> #include <vector> #include <algorithm> using namespace std; #pragma warning (disable: 4996) struct Node { int BeforeL, BeforeR; int AfterL, AfterR; }; bool operator<(const Node& a1, const Node& a2) { if (a1.BeforeL < a2.BeforeL) return true; return false; } class SegmentTree { public: int mod = 0; int size_ = 1; int tmp = 0; vector<vector<Node>> dat; // Initialize SegmentTree void Init(int sz, int mod_) { mod = mod_; while (size_ <= sz) size_ *= 2; Node ZERO = Node{ 0, mod - 1, 0, mod - 1 }; dat.resize(size_ * 2, vector<Node>{}); for (int i = size_; i < size_ * 2; i++) dat[i].push_back(ZERO); } // Add Information: A[pos] = x void update(int pos, int x) { pos += size_; dat[pos].clear(); dat[pos].push_back(Node{ 0, x - 1, (x + 1) % mod, (2 * x) % mod }); dat[pos].push_back(Node{ x, mod - 1, (2 * x) % mod, (mod - 1 + x) % mod }); } // Merge Vertex pos*2 and pos*2+1 void Merge(int pos) { for (int i = 0; i < dat[pos * 2].size(); i++) { int pos1 = lower_bound(dat[pos * 2 + 1].begin(), dat[pos * 2 + 1].end(), Node{ dat[pos * 2][i].AfterL + 1, 0, 0, 0 }) - dat[pos * 2 + 1].begin(); pos1--; int pos2 = lower_bound(dat[pos * 2 + 1].begin(), dat[pos * 2 + 1].end(), Node{ dat[pos * 2][i].AfterR + 1, 0, 0, 0 }) - dat[pos * 2 + 1].begin(); pos2--; if (dat[pos * 2][i].AfterL > dat[pos * 2][i].AfterR) pos2 += dat[pos * 2 + 1].size(); // Addition for (int j = pos1; j <= pos2; j++) { int idx = j % dat[pos * 2 + 1].size(); int cl = dat[pos * 2][i].AfterL; int cr = dat[pos * 2][i].AfterR; if (cl > cr) { if (j >= dat[pos * 2 + 1].size()) cl = 0; else cr = mod - 1; } // Calculate Actual cl, cr & Offset cl = max(cl, dat[pos * 2 + 1][idx].BeforeL); cr = min(cr, dat[pos * 2 + 1][idx].BeforeR); int offset1 = (dat[pos * 2][i].BeforeL - dat[pos * 2][i].AfterL); if (offset1 < 0) offset1 += mod; int offset2 = (dat[pos * 2 + 1][idx].AfterL - dat[pos * 2 + 1][idx].BeforeL); if (offset2 < 0) offset2 += mod; // Add to dat[pos] dat[pos].push_back(Node{ (offset1 + cl) % mod, (offset1 + cr) % mod, (offset2 + cl) % mod, (offset2 + cr) % mod }); } } } // Recursion void query_(int l, int r, int a, int b, int u) { if (l <= a && b <= r) { int pos1 = lower_bound(dat[u].begin(), dat[u].end(), Node{ tmp + 1, 0, 0, 0 }) - dat[u].begin(); pos1--; int offset = dat[u][pos1].AfterL - dat[u][pos1].BeforeL; if (offset < 0) offset += mod; tmp = (tmp + offset) % mod; return; } if (r <= a || b <= l) return; query_(l, r, a, ((a + b) >> 1), u * 2); query_(l, r, ((a + b) >> 1), b, u * 2 + 1); } // Answer Query [cl, cr) int query(int cl, int cr, int x) { tmp = x; query_(cl, cr, 0, size_, 1); return tmp; } }; // Input int N; char C[120009]; int M, A[120009]; int Q, L[120009], R[120009]; int LeftPos[120009], NumLeft; int RigtPos[120009], NumRigt; int NextQ[22][22][120009], Haba[22], UpLimit; long long SumLeft[22][120009]; long long SumRigt[22][120009]; long long SumRed[120009]; SegmentTree Z; // Initializing void Initialize() { for (int i = 1; i <= N; i++) { if (C[i] == 'B') { NumLeft += 1; LeftPos[NumLeft] = i; } if (C[i] == 'R') { NumRigt += 1; RigtPos[NumRigt] = i; } } LeftPos[0] = 0; LeftPos[NumLeft + 1] = N + 1; RigtPos[0] = 0; RigtPos[NumRigt + 1] = N + 1; reverse(RigtPos, RigtPos + NumRigt + 2); // Calculate NextQ while ((1 << UpLimit) < N / 2) UpLimit += 1; for (int i = 1; i <= UpLimit; i++) { Haba[i] = (1 << (i - 1)); } for (int i = 0; i <= UpLimit; i++) { for (int j = 0; j <= UpLimit; j++) { NextQ[i][j][M + 1] = M + 1; for (int k = M; k >= 0; k--) { NextQ[i][j][k] = NextQ[i][j][k + 1]; if (Haba[i] < A[k] && A[k] <= N - Haba[j] && (C[N] == 'R' || A[k] != N)) NextQ[i][j][k] = k; // Changed from uso1_e869120.cpp } } } // Calculate Cumulative Sum for (int i = 0; i <= UpLimit; i++) { SumLeft[i][0] = 0; SumRigt[i][0] = 0; for (int j = 1; j <= M; j++) { SumLeft[i][j] = SumLeft[i][j - 1]; if (A[j] <= Haba[i]) SumLeft[i][j] += A[j]; SumRigt[i][j] = SumRigt[i][j - 1]; if (N - Haba[i] < A[j]) SumRigt[i][j] += (N - A[j]); } } for (int i = 1; i <= N; i++) { SumRed[i] = SumRed[i - 1]; if (C[i] == 'R') SumRed[i] += 1; } } // Get number of 'R's when putting ball at place pos int GetNumR(int cl, int cr, int pos) { int val = LeftPos[cl] + (SumRed[RigtPos[cr] - 1] - SumRed[LeftPos[cl]]); if (pos != -1) { val += pos; if (RigtPos[cr] <= pos || (LeftPos[cl] < pos && C[pos] == 'B')) val += 1; val %= (N + 1); } return val; } // Answer query [bl, br] int solve(int bl, int br) { int IndexL = 0, LeftLevel = 0; int IndexR = 0, RigtLevel = 0; int CurrentButton = bl; // Repeat Binary Search while (true) { int Target = min(br + 1, NextQ[LeftLevel][RigtLevel][CurrentButton]); // Binary Search if (CurrentButton < Target) { int cl = CurrentButton, cm, cr = Target; int maxn = CurrentButton - 1; int maxL = IndexL; int maxR = IndexR; for (int i = 0; i < 22; i++) { cm = (cl + cr) / 2; int pos1 = min((long long)NumLeft + 1, IndexL + SumLeft[LeftLevel][cm] - SumLeft[LeftLevel][CurrentButton - 1]); int pos2 = min((long long)NumRigt + 1, IndexR + SumRigt[RigtLevel][cm] - SumRigt[RigtLevel][CurrentButton - 1]); if (LeftPos[pos1] + 1 < RigtPos[pos2]) { if (maxn < cm) { maxn = cm; maxL = pos1; maxR = pos2; } cl = cm; } else { cr = cm; } } // When it goes to phase #2 if (maxn != Target - 1) { int StartingPosition = GetNumR(maxL, maxR, A[maxn + 1]); return Z.query(maxn + 2, br + 1, StartingPosition); } CurrentButton = Target; IndexL = maxL; IndexR = maxR; } // If all query finished int CurrentR = GetNumR(IndexL, IndexR, -1); if (CurrentButton == br + 1) return CurrentR; // Performing "O(1) operation" int NewIndexL = IndexL; int NewIndexR = IndexR; int Change = 0; if (RigtPos[IndexR] <= A[CurrentButton] || (LeftPos[IndexL] < A[CurrentButton] && C[A[CurrentButton]] == 'B')) Change = 1; if (N - CurrentR >= A[CurrentButton]) NewIndexL += A[CurrentButton] + Change; else NewIndexR += (N + 1 - A[CurrentButton]) - Change; // When it goes to phase #2 if (LeftPos[min(NumLeft + 1, NewIndexL)] + 1 >= RigtPos[min(NumRigt + 1, NewIndexR)]) { return Z.query(CurrentButton + 1, br + 1, (CurrentR + Change + A[CurrentButton]) % (N + 1)); } IndexR = NewIndexR; IndexL = NewIndexL; CurrentButton += 1; // Update Level while (LeftLevel < UpLimit && Haba[LeftLevel + 1] <= LeftPos[IndexL]) LeftLevel += 1; while (RigtLevel < UpLimit && Haba[RigtLevel + 1] <= N + 1 - RigtPos[IndexR]) RigtLevel += 1; } } int main() { // Input scanf("%d%d", &N, &M); for (int i = 1; i <= N; i++) cin >> C[i]; for (int i = 1; i <= M; i++) scanf("%d", &A[i]); scanf("%d", &Q); for (int i = 1; i <= Q; i++) scanf("%d%d", &L[i], &R[i]); // Precount Z.Init(M + 2, N + 1); for (int i = 1; i <= M; i++) Z.update(i, A[i]); for (int i = Z.size_ - 1; i >= 1; i--) Z.Merge(i); Initialize(); // Answer Query for (int i = 1; i <= Q; i++) { printf("%d\n", solve(L[i], R[i])); } return 0; }

Compilation message (stderr)

Main.cpp:5: warning: ignoring '#pragma warning ' [-Wunknown-pragmas]
    5 | #pragma warning (disable: 4996)
      | 
Main.cpp: In member function 'void SegmentTree::Merge(int)':
Main.cpp:43:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<Node>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   43 |   for (int i = 0; i < dat[pos * 2].size(); i++) {
      |                   ~~^~~~~~~~~~~~~~~~~~~~~
Main.cpp:54:12: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<Node>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   54 |      if (j >= dat[pos * 2 + 1].size()) cl = 0;
      |          ~~^~~~~~~~~~~~~~~~~~~~~~~~~~
Main.cpp: In function 'int main()':
Main.cpp:221:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  221 |  scanf("%d%d", &N, &M);
      |  ~~~~~^~~~~~~~~~~~~~~~
Main.cpp:223:36: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  223 |  for (int i = 1; i <= M; i++) scanf("%d", &A[i]);
      |                               ~~~~~^~~~~~~~~~~~~
Main.cpp:224:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  224 |  scanf("%d", &Q);
      |  ~~~~~^~~~~~~~~~
Main.cpp:225:36: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  225 |  for (int i = 1; i <= Q; i++) scanf("%d%d", &L[i], &R[i]);
      |                               ~~~~~^~~~~~~~~~~~~~~~~~~~~~
#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...