제출 #1355588

#제출 시각아이디문제언어결과실행 시간메모리
1355588yogesh_saneTruck Driver (IOI23_deliveries)C++20
0 / 100
41 ms7628 KiB
#include "deliveries.h"
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int MAXN = 100005;
ll T_counts[MAXN];
ll edge_weights[MAXN]; // edge_weights[i] is the weight between city i and i+1
int num_cities;

struct SegmentTree {
    ll tree_sum[MAXN << 2];    // Stores sum of T[i] in range
    ll tree_weighted[MAXN << 2]; // Stores sum of (T[i] * distance_from_0) or similar
    // Note: For a line, we actually want to track S_in for each edge.
    // Let's use a simpler structure for the line.
} st;

// For Subtask 4 (Line), we can simplify the math:
// Total Time = Sum over all edges i: 2 * Weight_i * min(PrefixSum(i), Total - PrefixSum(i))
// There is a point 'K' where PrefixSum(K) > Total/2. 
// Before K, min is PrefixSum. After K, min is (Total - PrefixSum).

struct LineSegmentTree {
    ll t_sum[MAXN << 2];      // Sum of deliveries T[i]
    ll weighted_dist[MAXN << 2]; // Sum of T[i] * distance_from_0
    ll dist_from_0[MAXN];

    void update(int node, int l, int r, int idx, int val) {
        if (l == r) {
            t_sum[node] = val;
            weighted_dist[node] = (ll)val * dist_from_0[l];
            return;
        }
        int mid = (l + r) >> 1;
        if (idx <= mid) update(node << 1, l, mid, idx, val);
        else update(node << 1 | 1, mid + 1, r, idx, val);
        t_sum[node] = t_sum[node << 1] + t_sum[node << 1 | 1];
        weighted_dist[node] = weighted_dist[node << 1] + weighted_dist[node << 1 | 1];
    }

    // Standard Segment Tree Walk to find the 'Weighted Median'
    int find_centroid(int node, int l, int r, ll current_half) {
        if (l == r) return l;
        int mid = (l + r) >> 1;
        if (t_sum[node << 1] >= current_half)
            return find_centroid(node << 1, l, mid, current_half);
        else
            return find_centroid(node << 1 | 1, mid + 1, r, current_half - t_sum[node << 1]);
    }

    // Query sum of T[i] in range [ql, qr]
    ll query_t(int node, int l, int r, int ql, int qr) {
        if (ql > r || qr < l) return 0;
        if (ql <= l && r <= qr) return t_sum[node];
        int mid = (l + r) >> 1;
        return query_t(node << 1, l, mid, ql, qr) + query_t(node << 1 | 1, mid + 1, r, ql, qr);
    }

    // Query sum of T[i]*dist in range [ql, qr]
    ll query_w(int node, int l, int r, int ql, int qr) {
        if (ql > r || qr < l) return 0;
        if (ql <= l && r <= qr) return weighted_dist[node];
        int mid = (l + r) >> 1;
        return query_w(node << 1, l, mid, ql, qr) + query_w(node << 1 | 1, mid + 1, r, ql, qr);
    }
} line_st;

void init(int N, vector<int> U, vector<int> V, vector<int> W, vector<int> T) {
    num_cities = N;
    // Assuming line is 0-1-2-...-(N-1) based on problem constraints for this subtask
    // We calculate distance from city 0 to each city i
    line_st.dist_from_0[0] = 0;
    for (int i = 0; i < N - 1; i++) {
        // Find which node is "further" in the line. 
        // In a line subtask, usually U[i]=i, V[i]=i+1.
        int u = U[i], v = V[i], w = W[i];
        line_st.dist_from_0[max(u, v)] = w; 
    }
    for (int i = 1; i < N; i++) line_st.dist_from_0[i] += line_st.dist_from_0[i-1];

    for (int i = 0; i < N; i++) {
        T_counts[i] = T[i];
        line_st.update(1, 0, N - 1, i, T[i]);
    }
}

ll max_time(int s, int x) {
    line_st.update(1, 0, num_cities - 1, s, x);
    ll total_T = line_st.t_sum[1];
    
    // 1. Find the city K that acts as the "weighted median"
    int K = line_st.find_centroid(1, 0, num_cities - 1, (total_T + 1) / 2);

    // 2. Mathematical derivation for the line:
    // Distance = 2 * [ Sum_{i > K} (T_i * (dist_i - dist_K)) + Sum_{i < K} (T_i * (dist_K - dist_i)) ]
    // This can be expanded into prefix sums and weighted sums:
    ll dist_K = line_st.dist_from_0[K];
    
    ll left_t = line_st.query_t(1, 0, num_cities - 1, 0, K - 1);
    ll left_w = line_st.query_w(1, 0, num_cities - 1, 0, K - 1);
    
    ll right_t = line_st.query_t(1, 0, num_cities - 1, K + 1, num_cities - 1);
    ll right_w = line_st.query_w(1, 0, num_cities - 1, K + 1, num_cities - 1);

    ll ans = 2 * ((left_t * dist_K - left_w) + (right_w - right_t * dist_K));
    return ans;
}
#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...