結果

問題 No.259 セグメントフィッシング+
ユーザー qwewe
提出日時 2025-05-14 12:59:39
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 41 ms / 2,000 ms
コード長 7,553 bytes
コンパイル時間 600 ms
コンパイル使用メモリ 75,444 KB
実行使用メモリ 7,844 KB
最終ジャッジ日時 2025-05-14 13:00:42
合計ジャッジ時間 3,071 ms
ジャッジサーバーID
(参考情報)
judge3 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 23
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

// Define long long type for potentially large fish counts and sums.
typedef long long ll;

// Set a constant for the maximum possible value of P = 2N. N <= 2e5, so P <= 4e5.
// Add a small buffer for safety. The BIT array uses 1-based indexing internally.
const int MAXP = 400005; 
// Declare the Fenwick tree (BIT) array. Use long long to store sums, as total fish count can exceed 32-bit integer limit.
ll bit[MAXP];
// Variable to store the period P = 2N of the fish movement cycle.
int P; 

/**
 * @brief Adds 'delta' to the element at index 'idx' in the Fenwick tree (BIT).
 * The BIT uses 1-based indexing. Updates index 'idx' and all its ancestors.
 * 
 * @param idx The 1-based index to update.
 * @param delta The value to add at index 'idx'.
 */
void add(int idx, ll delta) {
    // Basic bounds check for 1-based index.
    if (idx <= 0 || idx > P) return; 
    // Traverse up the tree, updating relevant nodes.
    for (; idx <= P; idx += idx & -idx) { // `idx & -idx` gives the lowest set bit
        bit[idx] += delta;
    }
}

/**
 * @brief Queries the prefix sum up to index 'idx' (sum of elements from index 1 to idx).
 * The BIT uses 1-based indexing.
 * 
 * @param idx The 1-based index up to which the sum is required.
 * @return The prefix sum up to index 'idx'.
 */
ll query(int idx) {
    // Handle index out of bounds cases. Return 0 for invalid/zero index.
    if (idx <= 0) return 0; 
    // Clamp index to the maximum valid index P if it exceeds bounds.
    if (idx > P) idx = P; 
    ll sum = 0;
    // Traverse down from 'idx' using parent links, summing values.
    for (; idx > 0; idx -= idx & -idx) {
        sum += bit[idx];
    }
    return sum;
}

/**
 * @brief Calculates the sum of elements in a range [A, B] modulo P.
 * The range is defined on 0-based indices [0, P-1]. Handles wrap-around cases where A > B.
 * 
 * @param A The start index of the range (0-based).
 * @param B The end index of the range (0-based).
 * @return The sum of elements in the specified range modulo P.
 */
ll range_sum(int A, int B) {
    // Validate input indices A and B are within [0, P-1]. Defensive check.
     if (A < 0 || A >= P || B < 0 || B >= P) {
         // Invalid range indices, this might indicate a logic error elsewhere.
         return 0; 
    }
    
    // Convert 0-based indices A, B to 1-based indices used by the BIT.
    int A_1based = A + 1;
    int B_1based = B + 1;

    // Case 1: Standard interval [A, B] where A <= B.
    if (A <= B) {
        // The sum over [A, B] (0-based) is sum[1..B+1] - sum[1..A].
        // Using BIT functions: query(B_1based) - query(A_1based - 1).
        return query(B_1based) - query(A_1based - 1);
    } 
    // Case 2: Wrap-around interval [A, P-1] U [0, B] where A > B.
    else {
        // The sum is sum over [A, P-1] + sum over [0, B].
        // Using BIT functions: (query(P) - query(A_1based - 1)) + query(B_1based).
        return (query(P) - query(A_1based - 1)) + query(B_1based);
    }
}

int main() {
    // Optimize standard input/output operations for speed.
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int N; // Length of the fishing spot interval [0, N)
    int Q; // Number of queries
    cin >> N >> Q;

    // Calculate the period P = 2N based on the fish movement rules.
    P = 2 * N; 

    // Process Q queries sequentially.
    for (int i = 0; i < Q; ++i) {
        char type; // Type of query: 'L', 'R', or 'C'.
        cin >> type;

        // If query type is 'L' or 'R', it's a fish release event.
        if (type == 'L' || type == 'R') {
            ll t; // Time of release (up to 10^8).
            int y; // Position of release (0 <= y < N). Use int, N <= 2e5.
            ll z; // Number of fish released (up to 10^8). Use ll.
            cin >> t >> y >> z;

            ll k0; // Initial coordinate k0 in the state space [0, P-1].
            if (type == 'L') {
                // Fish released facing left at position y. Initial state (y, Left).
                // Map this state to coordinate k0 = 2N - 1 - y.
                k0 = (ll)2 * N - 1 - y;
            } else { // type == 'R'
                // Fish released facing right at position y. Initial state (y, Right).
                // Map this state to coordinate k0 = y.
                k0 = y;
            }

            // Calculate the invariant K for this batch of fish. 
            // K = (k0 - t) mod P. The position coordinate k(t) = (K + t) mod P.
            // Use modular arithmetic properties to ensure K is non-negative.
            // t % P ensures we handle large t correctly relative to the period P.
            ll K = (k0 - (t % P) + P) % P; 
            
            // Add the 'z' fish to the Fenwick tree at index K+1 (BIT is 1-based).
            add(K + 1, z);

        } 
        // If query type is 'C', it's a count query.
        else { 
            ll t; // Time of query (up to 10^8).
            int y, z_coord; // Query interval [y, z_coord). Use int for coordinates.
            cin >> t >> y >> z_coord;

            ll total_fish = 0; // Initialize the count for this query.

            // --- Contribution from fish potentially moving Right ---
            // These fish have state coordinates k(t) in [0, N-1].
            // Their position x(t) = k(t).
            // Condition to be counted: y <= x(t) < z_coord  =>  y <= k(t) < z_coord.
            // Combined condition on k(t): k(t) must be in the interval [max(0, y), min(N-1, z_coord-1)].
            int A1 = max(0, y); // Start of interval for k(t)
            int B1 = min(N - 1, z_coord - 1); // End of interval for k(t)
            
            // Check if the interval [A1, B1] is valid (non-empty).
            if (A1 <= B1) { 
                // Map the target k(t) interval [A1, B1] to the corresponding K interval [A1', B1'].
                // K = (k(t) - t) mod P.
                int A1_prime = (A1 - (int)(t % P) + P) % P; // Use (int)(t % P) as P is int range.
                int B1_prime = (B1 - (int)(t % P) + P) % P;
                // Add the sum over this K interval [A1', B1'] using range_sum function.
                total_fish += range_sum(A1_prime, B1_prime);
            }

            // --- Contribution from fish potentially moving Left ---
            // These fish have state coordinates k(t) in [N, 2N-1].
            // Their position x(t) = 2N - 1 - k(t).
            // Condition to be counted: y <= x(t) < z_coord  =>  y <= 2N - 1 - k(t) < z_coord.
            // Rearranging for k(t): 2N - z_coord <= k(t) <= 2N - 1 - y.
            // Combined condition on k(t): k(t) must be in [max(N, 2N - z_coord), min(2N - 1, 2N - 1 - y)].
            int A2 = max(N, 2 * N - z_coord); // Start of interval for k(t)
            int B2 = min(2 * N - 1, 2 * N - 1 - y); // End of interval for k(t)

            // Check if the interval [A2, B2] is valid (non-empty).
             if (A2 <= B2) { 
                // Map the target k(t) interval [A2, B2] to the corresponding K interval [A2', B2'].
                int A2_prime = (A2 - (int)(t % P) + P) % P;
                int B2_prime = (B2 - (int)(t % P) + P) % P;
                // Add the sum over this K interval [A2', B2'] using range_sum function.
                total_fish += range_sum(A2_prime, B2_prime);
            }

            // Output the final calculated total fish count for the query interval.
            cout << total_fish << "\n";
        }
    }

    return 0;
}
0