結果
| 問題 | 
                            No.1297 銅像
                             | 
                    
| コンテスト | |
| ユーザー | 
                             qwewe
                         | 
                    
| 提出日時 | 2025-05-14 13:12:44 | 
| 言語 | C++17  (gcc 13.3.0 + boost 1.87.0)  | 
                    
| 結果 | 
                             
                                TLE
                                 
                             
                            
                         | 
                    
| 実行時間 | - | 
| コード長 | 8,173 bytes | 
| コンパイル時間 | 842 ms | 
| コンパイル使用メモリ | 95,764 KB | 
| 実行使用メモリ | 7,848 KB | 
| 最終ジャッジ日時 | 2025-05-14 13:13:45 | 
| 合計ジャッジ時間 | 5,698 ms | 
| 
                            ジャッジサーバーID (参考情報)  | 
                        judge2 / judge5 | 
(要ログイン)
| ファイルパターン | 結果 | 
|---|---|
| sample | AC * 2 | 
| other | AC * 7 TLE * 1 -- * 13 | 
ソースコード
#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
#include <cmath> // Required for abs function
using namespace std;
// Use long long for costs as they can potentially exceed the range of a 32-bit integer.
// The problem statement specifies costs up to 10^12, and total cost can accumulate.
typedef long long ll;
// Define a sufficiently large value to represent infinity.
// The maximum possible total cost can be estimated. Suppose one craftsman builds all statues.
// Max cost could be roughly N * (max(a_i) + max_transport + max(b_i))
// Max transport cost is roughly N * C <= 10^5 * 10^6 = 10^11.
// Max cost ~ 10^5 * (10^12 + 10^11 + 10^12) ~ 10^5 * (2.1 * 10^12) ~ 2.1 * 10^17.
// This value fits within a 64-bit signed long long (max value ~9e18).
// We use 4e18 as a safe upper bound constant for INF, significantly larger than max possible cost.
const ll INF = 4e18; 
int main() {
    // Use faster I/O operations
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int N; // Number of islands and craftsmen
    ll C;  // Cost factor for transportation
    cin >> N >> C;
    // Store work fees (a_i) and design fees (b_i) for each craftsman i.
    // Using 0-based indexing for vectors a and b.
    vector<ll> a(N), b(N);
    for (int i = 0; i < N; ++i) {
        cin >> a[i] >> b[i];
    }
    // Dynamic Programming approach based on the observation that there exists an optimal solution
    // where the assignments are monotone: if craftsman i_j builds the statue on island j,
    // then i_j <= i_{j+1} for all j=1..N-1.
    // Let DP[j][k] be the minimum cost to build statues on islands 1 to j,
    // such that island j is assigned to craftsman k. The assignments for 1..j satisfy monotonicity.
    //
    // We can optimize space complexity by only keeping track of the DP values for the previous island (j-1)
    // to compute the values for the current island (j).
    // Use 1-based indexing for islands (j) and craftsmen (k) in DP states for clarity, matching the problem statement.
    
    // current_dp[k] will store DP[j][k] during computation for island j
    vector<ll> current_dp(N + 1, INF);
    // prev_dp[k] stores DP[j-1][k] from the previous island j-1
    vector<ll> prev_dp(N + 1, INF);
    
    // M_prev[k] will store the prefix minimum: min_{p=1..k} prev_dp[p]
    // This helps compute the transition efficiently.
    vector<ll> M_prev(N + 1, INF); 
    // Base case: j=1 (first island)
    // Calculate the cost if island 1 is assigned to craftsman k (k=1..N)
    for (int k = 1; k <= N; ++k) {
        // Transportation cost for craftsman k (at location k) to build on island 1 (at location 1)
        // Explicitly cast indices to ll to avoid potential intermediate overflow issues if N is large.
        ll transport_cost = abs((ll)k - 1LL) * C; 
        
        // Total cost = work fee a_k + transport cost + design fee b_k
        // The design fee b_k is always paid because this is the first time craftsman k is used in this path.
        // Access arrays a and b using 0-based index k-1.
        // Check for potential overflow before each addition.
        ll current_cost = a[k - 1];
        // Check if adding transport_cost overflows
        if (transport_cost > INF - current_cost) { 
             prev_dp[k] = INF; // Set to INF if overflow would occur
        } else {
            current_cost += transport_cost;
             // Check if adding design_fee b[k-1] overflows
            if (b[k - 1] > INF - current_cost) {
                prev_dp[k] = INF; // Set to INF if overflow would occur
            } else {
                prev_dp[k] = current_cost + b[k - 1];
            }
        }
    }
    // Compute DP table row by row, iterating through islands j from 2 to N
    for (int j = 2; j <= N; ++j) {
        // Compute prefix minima M_prev based on the DP values from the previous row (prev_dp corresponds to DP[j-1])
        M_prev[0] = INF; // Initialize base case for prefix minimum calculation
        for(int k = 1; k <= N; ++k) {
            M_prev[k] = min(M_prev[k-1], prev_dp[k]);
        }
        // Calculate current row DP values (current_dp corresponds to DP[j])
        fill(current_dp.begin(), current_dp.end(), INF); // Initialize current row DP values with INF
        
        // Iterate through all possible craftsmen k for island j
        for (int k = 1; k <= N; ++k) {
            // Calculate the cost incurred specifically for assigning island j to craftsman k.
            // This includes the work fee a_k and transportation cost |k-j|*C.
            ll variable_cost = a[k - 1]; // Work fee
            ll transport_cost = abs((ll)k - (ll)j) * C; // Transportation cost
            
            // Check for overflow when calculating variable_cost
            if (transport_cost > INF - variable_cost) { 
                 variable_cost = INF; // Use INF if overflow occurs
            } else {
                 variable_cost += transport_cost;
            }
            // If variable cost itself is INF (due to overflow or large base values), skip update for this k.
            if (variable_cost == INF) { 
                 continue;
            }
            // The recurrence relation for DP[j][k] is:
            // DP[j][k] = (a_k + C|k-j|) + min( DP[j-1][k],  b_k + min_{p=1..k-1} DP[j-1][p] )
            // This considers two possibilities for the state reaching (j, k):
            
            // Option 1: The craftsman for island j-1 was also k.
            // The cost is DP[j-1][k] + variable_cost_for_j.
            // Design fee b_k is already included in DP[j-1][k] if k was used.
            ll cost1 = INF;
            if (prev_dp[k] != INF) { // Check if the previous state is reachable
                 // Check for potential overflow before adding variable_cost
                 if (variable_cost > INF - prev_dp[k]) {
                     // cost1 remains INF if overflow would occur
                 } else {
                     cost1 = variable_cost + prev_dp[k];
                 }
            }
            // Option 2: The craftsman for island j-1 was p, where p < k.
            // The cost is min_{p=1..k-1} DP[j-1][p] + b_k + variable_cost_for_j.
            // The term min_{p=1..k-1} DP[j-1][p] is efficiently retrieved using M_prev[k-1].
            // The design fee b_k must be added because craftsman k is used for the first time
            // in the sequence of craftsmen when transitioning from p < k to k.
            ll cost2 = INF;
             if (M_prev[k - 1] != INF) { // Check if any path ending with p < k is reachable
                 ll min_prev_cost_prefix = M_prev[k - 1];
                 ll design_fee = b[k - 1];
                 
                 // Check for overflow when adding design fee b_k
                 if (min_prev_cost_prefix > INF - design_fee) { 
                     // If min_prev_cost + design_fee overflows, this path cost is effectively INF
                 } else {
                     ll combined_prev_cost = min_prev_cost_prefix + design_fee;
                     // Check for potential overflow when adding variable_cost
                     if (variable_cost > INF - combined_prev_cost) {
                        // cost2 remains INF if overflow would occur
                     } else {
                         cost2 = variable_cost + combined_prev_cost;
                     }
                 }
             }
            // The DP value DP[j][k] is the minimum cost from either Option 1 or Option 2.
            current_dp[k] = min(cost1, cost2);
        }
        
        // Update prev_dp for the next iteration (j+1). The computed 'current_dp' becomes the 'prev_dp'.
        prev_dp = current_dp;
    }
    // The final minimum total cost is the minimum value in the last row of the DP table (j=N),
    // minimized over all possible craftsmen k assigned to the last island N.
    ll min_total_cost = INF;
    // After the loop for j=N finishes, prev_dp holds the DP[N] values
    for (int k = 1; k <= N; ++k) {
        min_total_cost = min(min_total_cost, prev_dp[k]); 
    }
    cout << min_total_cost << endl;
    return 0;
}
            
            
            
        
            
qwewe