20
思路:一开始的做法是,从最左端的点开始逐渐往右移动,移动过程中记录左边的贡献和右边的贡献,每次移动更新下当前的带权距离和然后更新下左右贡献即可。
还看到了另一个很好的做法,把每个点的权值w看做是w个点在这,这样就转换成了中位数问题,直接找中位数的那个点就可以了。
方法一代码:
import java.util.Arrays; import java.util.Scanner; class node implements Comparable<node> { int x, w; @Override public int compareTo(node o) { return x - o.x; } } public class Main { static final int maxn = 100005; static node[] a = new node[maxn]; public static void main(String[] args) { Scanner sc = new Scanner(System.in); for (int i = 0; i < maxn; i++) a[i] = new node(); while (sc.hasNext()) { int n = sc.nextInt(); for (int i = 0; i < n; i++) { a[i].x = sc.nextInt(); a[i].w = sc.nextInt(); } Arrays.sort(a, 0, n); int l = a[0].x, r = a[n - 1].x; for (int i = 1; i < n; i++) { if (a[i].x < l) l = a[i].x; if (a[i].x > r) r = a[i].x; } long lval = 0, rval = 0; long dis = 0; for (int i = 0; i < n; i++) { dis += (long) (a[i].x - l) * a[i].w; rval += a[i].w; } long ans = dis; int cur = 0; lval = a[0].w; rval -= a[0].w; for (int i = 1; i < n; i++) { dis -= rval * (a[i].x - a[i - 1].x); dis += lval * (a[i].x - a[i - 1].x); if (dis < ans) ans = dis; rval -= a[i].w; lval += a[i].w; } System.out.println(ans); } } }方法二代码:
import java.util.Arrays; import java.util.Scanner; class node implements Comparable<node> { int x, w; @Override public int compareTo(node o) { return x - o.x; } } public class Main { static final int maxn = 100005; static node[] a = new node[maxn]; public static void main(String[] args) { Scanner sc = new Scanner(System.in); for (int i = 0; i < maxn; i++) a[i] = new node(); while (sc.hasNext()) { int n = sc.nextInt(); long sum = 0; for (int i = 0; i < n; i++) { a[i].x = sc.nextInt(); a[i].w = sc.nextInt(); sum += a[i].w; } sum /= 2; Arrays.sort(a, 0, n); int num = 0, idx = 0; for (int i = 0; i < n; i++) { num += a[i].w; if (num > sum) { idx = a[i].x; break; } } long ans = 0; for (int i = 0; i < n; i++) { ans += Math.abs((long)(a[i].x-idx)*a[i].w); } System.out.println(ans); } } }