250623 Bulldozer

Jongleee·2025년 6월 23일
0

TIL

목록 보기
938/970
private static final int MAX_N = 4002;
private static final int SEG_SIZE = 1 << 13;
private static final long INF = (long) 1e13;

private static class SegmentTree {
	long[] maxTree = new long[SEG_SIZE];
	long[] minTree = new long[SEG_SIZE];
	long[] diffTree = new long[SEG_SIZE];
	int size = SEG_SIZE >> 1;

	void init() {
		Arrays.fill(maxTree, -INF);
		Arrays.fill(minTree, INF);
		Arrays.fill(diffTree, 0);
	}

	void update(int index, long value) {
		int k = index + size - 1;
		maxTree[k] = value;
		minTree[k] = value;
		while (k > 0) {
			k = (k - 1) >> 1;
			maxTree[k] = Math.max(maxTree[2 * k + 1], maxTree[2 * k + 2]);
			minTree[k] = Math.min(minTree[2 * k + 1], minTree[2 * k + 2]);
			diffTree[k] = Math.max(diffTree[2 * k + 1], diffTree[2 * k + 2]);
			diffTree[k] = Math.max(diffTree[k], maxTree[2 * k + 2] - minTree[2 * k + 1]);
		}
	}

	long getMaxDifference() {
		return diffTree[0];
	}
}

private static class Point {
	long x, y, weight;

	Point(long x, long y, long weight) {
		this.x = x;
		this.y = y;
		this.weight = weight;
	}
}

private static class SwapOperation implements Comparable<SwapOperation> {
	long dx, dy;
	int u, v;

	SwapOperation(long dx, long dy, int u, int v) {
		this.dx = dx;
		this.dy = dy;
		this.u = u;
		this.v = v;
	}

	boolean isSameDirection(SwapOperation other) {
		return this.dx * other.dy == this.dy * other.dx;
	}

	@Override
	public int compareTo(SwapOperation other) {
		long lhs = this.dx * other.dy;
		long rhs = this.dy * other.dx;
		if (lhs == rhs) {
			if (this.u != other.u)
				return Integer.compare(other.u, this.u);
			return Integer.compare(other.v, this.v);
		}
		return -Long.compare(lhs, rhs);
	}
}

public static void main(String[] args) throws Exception {
	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	int n = Integer.parseInt(br.readLine());
	long[] x = new long[MAX_N];
	long[] y = new long[MAX_N];
	long[] w = new long[MAX_N];

	for (int i = 0; i < n; i++) {
		StringTokenizer st = new StringTokenizer(br.readLine());
		x[i] = Long.parseLong(st.nextToken());
		y[i] = Long.parseLong(st.nextToken());
		w[i] = Long.parseLong(st.nextToken());
	}

	List<Point> points = new ArrayList<>();
	for (int i = 0; i < n; i++) {
		points.add(new Point(x[i], y[i], w[i]));
	}
	points.sort(Comparator.comparingLong((Point p) -> p.x).thenComparingLong(p -> p.y));

	for (int i = 0; i < n; i++) {
		x[i] = points.get(i).x;
		y[i] = points.get(i).y;
		w[i] = points.get(i).weight;
	}

	List<SwapOperation> swaps = new ArrayList<>();
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (x[i] < x[j]) {
				swaps.add(new SwapOperation(y[i] - y[j], x[j] - x[i], Math.min(i, j), Math.max(i, j)));
			}
		}
	}
	swaps.sort(null);

	long[] prefixSum = new long[MAX_N];
	prefixSum[0] = 0;
	for (int i = 1; i <= n; i++) {
		prefixSum[i] = prefixSum[i - 1] + w[i - 1];
	}

	int[] indices = new int[MAX_N];
	for (int i = 0; i < n; i++) {
		indices[i] = i + 1;
	}

	SegmentTree segmentTree = new SegmentTree();
	segmentTree.init();
	for (int i = 0; i <= n; i++) {
		segmentTree.update(i, prefixSum[i]);
	}

	long result = segmentTree.getMaxDifference();
	for (int i = 0; i < swaps.size(); i++) {
		int u = swaps.get(i).u;
		int v = swaps.get(i).v;

		prefixSum[indices[u]] += prefixSum[indices[u] + 1] - 2 * prefixSum[indices[u]] + prefixSum[indices[u] - 1];
		segmentTree.update(indices[u], prefixSum[indices[u]]);
		int temp = indices[u];
		indices[u] = indices[v];
		indices[v] = temp;

		if (i == swaps.size() - 1 || !swaps.get(i).isSameDirection(swaps.get(i + 1))) {
			result = Math.max(result, segmentTree.getMaxDifference());
		}
	}

	System.out.println(result);
}

출처:https://www.acmicpc.net/problem/16783

0개의 댓글