結果
問題 |
No.2101 [Cherry Alpha N] ずっとこの数列だったらいいのに
|
ユーザー |
![]() |
提出日時 | 2025-05-14 13:09:16 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 294 ms / 6,000 ms |
コード長 | 8,715 bytes |
コンパイル時間 | 1,069 ms |
コンパイル使用メモリ | 83,844 KB |
実行使用メモリ | 55,500 KB |
最終ジャッジ日時 | 2025-05-14 13:10:43 |
合計ジャッジ時間 | 19,173 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 42 |
ソースコード
#include <vector> // For std::vector #include <iostream> // For input/output streams (cin, cout) #include <algorithm> // For std::sort #include <vector> // Included again, typically not needed but harmless // Using namespace std globally is common in competitive programming // but generally avoided in larger projects to prevent name collisions. using namespace std; // Define long long type alias for convenience, used for large sums. typedef long long ll; // Fenwick tree structure (Binary Indexed Tree) // Supports point updates and prefix sum queries in O(log N) time. struct FenwickTree { vector<ll> tree; // Stores the Fenwick tree data using long long for potentially large sums int size; // Size of the array the Fenwick tree represents // Constructor initializes the tree of size n. // Uses n+1 storage for 1-based indexing convenience. FenwickTree(int n) : size(n) { tree.assign(n + 1, 0); // Initialize tree elements to 0 } // Adds delta to the element at index idx (1-based). // Updates the tree structure accordingly. void update(int idx, ll delta) { // Check for invalid index (must be within 1 to size) if (idx <= 0 || idx > size) return; // Traverse up the tree structure, updating relevant nodes for (; idx <= size; idx += idx & -idx) { // idx & -idx gives the lowest set bit tree[idx] += delta; } } // Queries the prefix sum up to index idx (1-based). // Returns the sum of elements from index 1 to idx. ll query(int idx) { // Handle edge cases: index out of bounds if (idx <= 0) return 0; // Query up to 0 or negative index is 0 if (idx > size) idx = size; // Cap index if it exceeds tree size ll sum = 0; // Traverse down the tree structure, summing relevant nodes for (; idx > 0; idx -= idx & -idx) { sum += tree[idx]; } return sum; } // Queries the sum of elements in the range [L, R] (1-based). // Calculated as prefix_sum(R) - prefix_sum(L-1). ll query_range(int L, int R) { if (L > R) return 0; // Handle empty or invalid range // query(L-1) correctly handles L=1 because query(0) returns 0. return query(R) - query(L - 1); } }; // Structure to represent events (queries or state transitions) // Used for the sweep-line algorithm approach. struct Event { int time; // Time at which the event occurs (D for query, T_i or Z_i for transition) int type; // Event type: 0 for query, 1 for transition 1->2a/2b, 2 for transition 2a->2b int idx; // Index 'i' of the element involved in a transition event int L, R; // Range [L, R] for a query event int query_idx; // Original index of the query (to store the result correctly) ll valA; // Initial value A[i] needed for transition type 1 ll valY; // Value Y_i = A[i] + T[i] - 1 needed for transitions // Custom comparison operator for sorting events. // Primary sort key is time. // Secondary sort key is type, ensuring transitions are processed before queries at the same time. bool operator<(const Event& other) const { if (time != other.time) { return time < other.time; // Sort by time ascending } // If times are equal, process transitions (types 1, 2) before queries (type 0). // Higher type number indicates a transition, so sort types descending (2 > 1 > 0). return type > other.type; } }; int main() { // Optimize standard I/O operations for speed ios_base::sync_with_stdio(false); cin.tie(NULL); int N; // Number of elements in the sequence cin >> N; // Use vectors of size N+1 for 1-based indexing consistency with Fenwick trees vector<ll> A(N + 1); vector<ll> T(N + 1); vector<Event> events; // Vector to store all events // Initialize three Fenwick trees: FenwickTree ft1(N); // Stores sum of A_i for elements currently in state 1 FenwickTree ft2a_Y(N); // Stores sum of Y_i = A_i + T_i - 1 for elements in state 2a FenwickTree ft2a_count(N); // Stores count (1 per element) of elements in state 2a // Read input for each element, initialize state, and create transition events for (int i = 1; i <= N; ++i) { cin >> A[i] >> T[i]; // Calculate Y_i and Z_i using long long to prevent potential overflow issues. ll Yi = A[i] + T[i] - 1; ll Zi_ll = A[i] + T[i]; // The problem constraints state T_i >= 1. // Time points T_i and Z_i can be up to 2*10^9, fitting safely within a standard 32-bit signed int. int Ti_int = (int)T[i]; int Zi_int = (int)Zi_ll; // Initialize FT1: At time D=0, all elements are in state 1. Add their initial A[i] value. ft1.update(i, A[i]); // Create the first transition event for element i: state 1 -> 2a/2b. // This happens at time T_i. We pass A[i] and Y[i] needed for the update logic. events.push_back({Ti_int, 1, i, 0, 0, -1, A[i], Yi}); // Create the second transition event for element i: state 2a -> 2b. // This happens at time Z_i = A_i + T_i. // This transition only happens if the element enters state 2a, which requires A[i] > 0. if (A[i] > 0) { // Pass Y[i] needed for removal from state 2a contribution. events.push_back({Zi_int, 2, i, 0, 0, -1, 0, Yi}); } } int Q; // Number of queries cin >> Q; vector<ll> results(Q); // Vector to store the answer for each query // Read queries and add them as events for (int q = 0; q < Q; ++q) { int D; // Query day D int L, R; // Query range [L, R] cin >> D >> L >> R; // Problem states D_q >= 0. events.push_back({D, 0, 0, L, R, q, 0, 0}); // Type 0 for query events } // Sort all events based on time, then type (transitions before queries) sort(events.begin(), events.end()); // Process events in sorted order using the sweep-line approach for (const auto& ev : events) { if (ev.type == 0) { // Process query event int D = ev.time; // Current time for the query int L = ev.L; // Left boundary of query range int R = ev.R; // Right boundary of query range int q_idx = ev.query_idx; // Original index of this query // Query the Fenwick trees to get necessary sums and counts for the range [L, R] ll sum1 = ft1.query_range(L, R); // Sum of A_i for elements in state 1 ll sum2a_Y = ft2a_Y.query_range(L, R); // Sum of Y_i for elements in state 2a ll count2a = ft2a_count.query_range(L, R); // Count of elements in state 2a // Calculate the final answer using the derived formula: Sum = Sum1 + Sum2a_Y - D * Count2a // Use long long for the multiplication D * Count2a to prevent overflow. results[q_idx] = sum1 + sum2a_Y - (ll)D * count2a; } else if (ev.type == 1) { // Process transition event: 1 -> 2a/2b int i = ev.idx; // Index of the element transitioning ll Ai = ev.valA; // Initial value A[i] ll Yi = ev.valY; // Value Y[i] = A[i] + T[i] - 1 // Element leaves state 1. Remove its contribution A[i] from FT1. ft1.update(i, -Ai); // Check if element moves to state 2a or directly to 2b. if (Ai > 0) { // If A[i] > 0, element moves to state 2a. // Add its contribution to FT2a_Y and FT2a_count. ft2a_Y.update(i, Yi); ft2a_count.update(i, 1); } // If Ai == 0, element moves directly from state 1 to state 2b. // State 2b has 0 contribution, so no updates needed for FT2a trees. } else { // Process transition event: 2a -> 2b (ev.type == 2) int i = ev.idx; // Index of the element transitioning ll Yi = ev.valY; // Value Y[i] = A[i] + T[i] - 1 // This event only occurs if A[i] > 0 initially. // Element leaves state 2a and moves to state 2b. // Remove its contribution from FT2a_Y and FT2a_count. ft2a_Y.update(i, -Yi); ft2a_count.update(i, -1); } } // Output the results for all queries, each on a new line. for (int q = 0; q < Q; ++q) { cout << results[q] << "\n"; } return 0; // Indicate successful execution }