李超线段树

image

//最小


#include <bits/stdc++.h>

using i64 = long long;

struct Line {
    i64 m, b;
    Line(i64 _m = 0, i64 _b = LLONG_MAX) : m(_m), b(_b) {}
    i64 eval(i64 x) const { return m * x + b; }
};

struct Node {
    Line ln;
    Node *lch, *rch;
    Node(const Line& _ln) : ln(_ln), lch(nullptr), rch(nullptr) {}
};

struct LiChao {
    i64 L, R;
    Node* root;

    LiChao(i64 _L, i64 _R) : L(_L), R(_R), root(nullptr) {}

    void add_line(i64 m, i64 b) {
        insert(root, L, R, Line(m, b));
    }

    i64 query(i64 x) const {
        return query_min(root, L, R, x);
    }

    void insert(Node*& nd, i64 l, i64 r, Line ln) {
        if (!nd) {
            nd = new Node(ln);
            return;
        }
        i64 mid = (l + r) >> 1;

        bool left  = ln.eval(l)   < nd->ln.eval(l);
        bool mid_   = ln.eval(mid) < nd->ln.eval(mid);

        if (mid_) 
            std::swap(ln, nd->ln);

        if (l == r) 
            return;

        if (left != mid_)
            insert(nd->lch, l, mid, ln);
        else
            insert(nd->rch, mid + 1, r, ln);
    }

    i64 query_min(Node* nd, i64 l, i64 r, i64 x) const {
        if (!nd) return LLONG_MAX;
        i64 res = nd->ln.eval(x);
        if (l == r) return res;
        i64 mid = (l + r) >> 1;
        if (x <= mid)
            return std::min(res, query_min(nd->lch, l, mid, x));
        else
            return std::min(res, query_min(nd->rch, mid + 1, r, x));
    }
};

void solve() {
	int n, m;
	std::cin >> n >> m;
	std::vector<std::tuple<int, int, i64, int>> edges(m);
	std::vector<std::vector<std::pair<int, i64>>> adj(n);
	std::vector<std::vector<std::pair<int, i64>>> radj(n);
	for (int i = 0; i < m; ++ i) {
		int u, v, w;
		i64 t;
		std::cin >> u >> v >> t >> w;
		-- u, -- v;
		adj[u].emplace_back(v, t);
		radj[v].emplace_back(u, t);
		edges[i] = {u, v, t, w};
	}	

	const i64 inf = 1e18;
	auto dijkstra = [&](std::vector<i64> & dist, std::vector<std::vector<std::pair<int, i64>>> & adj, int s) -> void {
		using PII = std::pair<i64, int>;
		std::priority_queue<PII, std::vector<PII>, std::greater<PII>> heap;
		std::fill(dist.begin(), dist.end(), inf);

		dist[s] = 0;
		heap.emplace(dist[s], s);
		while (heap.size()) {
			auto [d, u] = heap.top(); heap.pop();
			if (d != dist[u]) {
				continue;
			}

			for (auto & [v, w] : adj[u]) {
				if (dist[v] > dist[u] + w) {
					dist[v] = dist[u] + w;
					heap.emplace(dist[v], v);
				}
			}
		}
	};

	std::vector<i64> d1(n), dn(n);
	dijkstra(d1, adj, 0);
	dijkstra(dn, radj, n - 1);

	LiChao tr(1, 1e9);

	for (auto & [u, v, t, w] : edges) {
		i64 d = d1[u] + dn[v];
		if (d < inf) {
			tr.add_line(-w, d + t);
		}
	}

	int q;
	std::cin >> q;
	while (q -- ) {
		i64 k;
		std::cin >> k;
		std::cout << tr.query(k) << "\n";
	}
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}
posted on 2025-10-22 19:17  下头小美  阅读(4)  评论(0)    收藏  举报