|
|
package class_2022_03_3_week;
|
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
|
// 来自美团
|
|
|
// void add(int L, int R, int C)代表在arr[L...R]上每个数加C
|
|
|
// int get(int L, int R)代表查询arr[L...R]上的累加和
|
|
|
// 假设你可以在所有操作开始之前,重新排列arr
|
|
|
// 请返回每一次get查询的结果都加在一起最大能是多少
|
|
|
// 输入参数:
|
|
|
// int[] arr : 原始数组
|
|
|
// int[][] ops,二维数组每一行解释如下:
|
|
|
// [a,b,c],如果数组有3个数,表示调用add(a,b,c)
|
|
|
// [a,b],如果数组有2个数,表示调用get(a,b)
|
|
|
// a和b表示arr范围,范围假设从1开始,不从0开始
|
|
|
// 输出:
|
|
|
// 假设你可以在开始时重新排列arr,返回所有get操作返回值累计和最大是多少?
|
|
|
public class Code04_ArrangeAddGetMax {
|
|
|
|
|
|
public static int maxGets(int[] arr, int[][] ops) {
|
|
|
int n = arr.length;
|
|
|
SegmentTree getTree = new SegmentTree(n);
|
|
|
for (int[] op : ops) {
|
|
|
if (op.length == 2) {
|
|
|
getTree.add(op[0], op[1], 1);
|
|
|
}
|
|
|
}
|
|
|
int[][] getCnts = new int[n][2];
|
|
|
for (int i = 1, j = 0; i <= n; i++, j++) {
|
|
|
getCnts[j][0] = j;
|
|
|
getCnts[j][1] = getTree.get(i, i);
|
|
|
}
|
|
|
Arrays.sort(getCnts, (a, b) -> a[1] - b[1]);
|
|
|
Arrays.sort(arr);
|
|
|
int[] reArrange = new int[n];
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
reArrange[getCnts[i][0]] = arr[i];
|
|
|
}
|
|
|
SegmentTree st = new SegmentTree(reArrange);
|
|
|
int ans = 0;
|
|
|
for (int[] op : ops) {
|
|
|
if (op.length == 3) {
|
|
|
st.add(op[0], op[1], op[2]);
|
|
|
} else {
|
|
|
ans += st.get(op[0], op[1]);
|
|
|
}
|
|
|
}
|
|
|
return ans;
|
|
|
}
|
|
|
|
|
|
public static class SegmentTree {
|
|
|
private int n;
|
|
|
private int[] arr;
|
|
|
private int[] sum;
|
|
|
private int[] lazy;
|
|
|
|
|
|
public SegmentTree(int size) {
|
|
|
n = size + 1;
|
|
|
sum = new int[n << 2];
|
|
|
lazy = new int[n << 2];
|
|
|
n--;
|
|
|
}
|
|
|
|
|
|
public SegmentTree(int[] origin) {
|
|
|
n = origin.length + 1;
|
|
|
arr = new int[n];
|
|
|
for (int i = 1; i < n; i++) {
|
|
|
arr[i] = origin[i - 1];
|
|
|
}
|
|
|
sum = new int[n << 2];
|
|
|
lazy = new int[n << 2];
|
|
|
build(1, --n, 1);
|
|
|
}
|
|
|
|
|
|
private void build(int l, int r, int rt) {
|
|
|
if (l == r) {
|
|
|
sum[rt] = arr[l];
|
|
|
return;
|
|
|
}
|
|
|
int mid = (l + r) >> 1;
|
|
|
build(l, mid, rt << 1);
|
|
|
build(mid + 1, r, rt << 1 | 1);
|
|
|
pushUp(rt);
|
|
|
}
|
|
|
|
|
|
private void pushUp(int rt) {
|
|
|
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
|
|
|
}
|
|
|
|
|
|
private void pushDown(int rt, int ln, int rn) {
|
|
|
if (lazy[rt] != 0) {
|
|
|
lazy[rt << 1] += lazy[rt];
|
|
|
sum[rt << 1] += lazy[rt] * ln;
|
|
|
lazy[rt << 1 | 1] += lazy[rt];
|
|
|
sum[rt << 1 | 1] += lazy[rt] * rn;
|
|
|
lazy[rt] = 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public void add(int L, int R, int C) {
|
|
|
add(L, R, C, 1, n, 1);
|
|
|
}
|
|
|
|
|
|
private void add(int L, int R, int C, int l, int r, int rt) {
|
|
|
if (L <= l && r <= R) {
|
|
|
sum[rt] += C * (r - l + 1);
|
|
|
lazy[rt] += C;
|
|
|
return;
|
|
|
}
|
|
|
int mid = (l + r) >> 1;
|
|
|
pushDown(rt, mid - l + 1, r - mid);
|
|
|
if (L <= mid) {
|
|
|
add(L, R, C, l, mid, rt << 1);
|
|
|
}
|
|
|
if (R > mid) {
|
|
|
add(L, R, C, mid + 1, r, rt << 1 | 1);
|
|
|
}
|
|
|
pushUp(rt);
|
|
|
}
|
|
|
|
|
|
public int get(int L, int R) {
|
|
|
return query(L, R, 1, n, 1);
|
|
|
}
|
|
|
|
|
|
private int query(int L, int R, int l, int r, int rt) {
|
|
|
if (L <= l && r <= R) {
|
|
|
return sum[rt];
|
|
|
}
|
|
|
int mid = (l + r) >> 1;
|
|
|
pushDown(rt, mid - l + 1, r - mid);
|
|
|
int ans = 0;
|
|
|
if (L <= mid) {
|
|
|
ans += query(L, R, l, mid, rt << 1);
|
|
|
}
|
|
|
if (R > mid) {
|
|
|
ans += query(L, R, mid + 1, r, rt << 1 | 1);
|
|
|
}
|
|
|
return ans;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
int[] arr = { 1, 2, 3, 4, 5 };
|
|
|
int[][] ops = { { 1, 3 }, { 2, 4 }, { 1, 5 } };
|
|
|
System.out.println(maxGets(arr, ops));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|