#include using namespace std; using u32 = uint32_t; using u64 = uint64_t; static constexpr int B = 4; static constexpr int CHUNKS = 8; static constexpr int CHUNK_VALUES = 1 << B; static constexpr int NONZERO_MASKS = CHUNK_VALUES - 1; static constexpr u32 FULL = (1u << 30) - 1; class MaskedPrefixSum { private: int n; size_t width; vector pref; size_t offset(int chunk, int mask) const { // mask は 1 以上 15 以下 return ( static_cast(chunk) * NONZERO_MASKS + (mask - 1) ) * width; } public: explicit MaskedPrefixSum(const vector& a) : n(static_cast(a.size()) - 1), width(static_cast(n) + 1), pref( static_cast(CHUNKS) * NONZERO_MASKS * width, 0 ) { for (int chunk = 0; chunk < CHUNKS; ++chunk) { const int shift = B * chunk; for (int mask = 1; mask < CHUNK_VALUES; ++mask) { const size_t base = offset(chunk, mask); for (int i = 1; i <= n; ++i) { const u32 part = (a[i] >> shift) & (CHUNK_VALUES - 1); pref[base + i] = pref[base + i - 1] + (part & static_cast(mask)); } } } } u64 rangeMaskedSum(int l, int r, u32 mask) const { u64 result = 0; for (int chunk = 0; chunk < CHUNKS; ++chunk) { const int shift = B * chunk; const int chunkMask = static_cast( (mask >> shift) & (CHUNK_VALUES - 1) ); if (chunkMask == 0) { continue; } const size_t base = offset(chunk, chunkMask); const u32 partSum = pref[base + r] - pref[base + l - 1]; result += static_cast(partSum) << shift; } return result; } }; struct Segment { int l; int r; u32 keepMask; u32 oneMask; }; static inline void appendMerged( vector& segments, const Segment& segment ) { if (segment.l > segment.r) { return; } if ( !segments.empty() && segments.back().r + 1 == segment.l && segments.back().keepMask == segment.keepMask && segments.back().oneMask == segment.oneMask ) { segments.back().r = segment.r; } else { segments.push_back(segment); } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N, M; cin >> N >> M; vector A(N + 1); for (int i = 1; i <= N; ++i) { cin >> A[i]; } vector l(M), r(M), L(M), R(M); vector x(M); for (int& value : l) { cin >> value; } for (int& value : r) { cin >> value; } for (u32& value : x) { cin >> value; } for (int& value : L) { cin >> value; } for (int& value : R) { cin >> value; } MaskedPrefixSum prefix(A); int Q; cin >> Q; vector segments; vector nextSegments; segments.reserve(32); nextSegments.reserve(32); for ( int problemIndex = 1; problemIndex <= Q; ++problemIndex ) { int s, q; cin >> s >> q; u32 y = static_cast(problemIndex); segments.clear(); nextSegments.clear(); segments.push_back({ 1, N, FULL, 0 }); for (int j = 1; j <= q; ++j) { // 問題文の z は 1-indexed const int z = ((s + j) % M) + 1; const int index = z - 1; auto transformedPosition = [&](int p) -> int { return clamp( p ^ static_cast(y), 1, N ); }; const int u = transformedPosition(l[index]); const int v = transformedPosition(r[index]); const int U = transformedPosition(L[index]); const int V = transformedPosition(R[index]); const int updateL = min(u, v); const int updateR = max(u, v); const int sumL = min(U, V); const int sumR = max(U, V); const u32 operationMask = x[index] ^ y; nextSegments.clear(); for (const Segment& segment : segments) { if ( segment.r < updateL || updateR < segment.l ) { appendMerged(nextSegments, segment); continue; } // 更新区間より左側 if (segment.l < updateL) { appendMerged( nextSegments, { segment.l, updateL - 1, segment.keepMask, segment.oneMask } ); } // 更新区間との共通部分 Segment middle{ max(segment.l, updateL), min(segment.r, updateR), segment.keepMask, segment.oneMask }; if (z % 2 == 0) { // value := value | operationMask middle.keepMask &= (FULL ^ operationMask); middle.oneMask |= operationMask; } else { // value := value & operationMask middle.keepMask &= operationMask; middle.oneMask &= operationMask; } appendMerged(nextSegments, middle); // 更新区間より右側 if (updateR < segment.r) { appendMerged( nextSegments, { updateR + 1, segment.r, segment.keepMask, segment.oneMask } ); } } segments.swap(nextSegments); u64 sum = 0; for (const Segment& segment : segments) { const int left = max(segment.l, sumL); const int right = min(segment.r, sumR); if (left > right) { continue; } const u64 length = static_cast(right - left + 1); sum += length * segment.oneMask; sum += prefix.rangeMaskedSum( left, right, segment.keepMask ); } // 2^30 で割った余り y = static_cast(sum & FULL); } cout << y << '\n'; } return 0; }