没有测试用例、没对极限数据进行处理,只是用最简单的方式写了一个通过标准测试的代码
原题目是 >>> 对数组A[N],定义如下操作:
C x y : 将A[x] 修改为y
L x y : 求区间[x,y]的左费用
R x y : 求区间[x,y]的右费用
其中左费用定义为∑A(i)*(i-x+1),右费用定义为∑A(i)*(y-i+1)
由于L和R操作的结果可能会非常大,因此要求计算结果对ie9+7取余(我能说我不会吗……)
1<=N<=1e5 ; 1<= A[i] <= 1000
class Main {
// 处理输入
public static void main(String[] args) {
System.out.println("hello https://tool.lu/");
int[] data = {1,5,2,4,9,3,5,4,7,1,5,9};
int[][] operate = {
{'L'+0, 1, 3},
{'C'+0, 1, 10},
{'R'+0, 1, 3}
};
int[] results = new Main().solve(data, operate);
for(int x : results) {
System.out.print(x+"\t");
}
System.out.println();
}
// 处理操作
public int[] solve(int[] data, int[][] operate) {
int[] results = new int[operate.length];
A a = A.create(data);
for(int i=0; i<operate.length; ++i) {
int[] op = operate[i];
if(op[0] == 0+'C') {
// update
a.update(op[1], op[2]-data[op[1]]);
} else if(op[0] == 0+'L') {
// sumL
results[i] = a.sumL(op[1], op[2]);
} else if(op[0] == 0+'R') {
// sumR
results[i] = a.sumR(op[1], op[2]);
} else {
throw new RuntimeException("What the fuck?!!!");
}
}
return results;
}
}
class A {
// 区间左右下标
int left;
int right;
// 每个节点储存当前节点的区间的Sum、L、R操作结果
int areaSum;
int areaL;
int areaR;
// 二叉树
A father;
A son1;
A son2;
// to be delete
boolean hasSon;
// 对data数据的预处理
public static A create(int[] data) {
A a = new A();
a.left = 0;
a.right = data.length-1;
// 区间为双含索引
return a.create(data, a.left, a.right, a);
}
// this == father
private A create(int[] data, int left, int right, A father) {
// 节点下分至数组中的每个数上
if(left == right) {
father.areaSum = father.areaL = father.areaR = data[left];
return father;
} /*else if(right-left == 1) {
father.areaSum = data[left] + data[right];
father.areaL = data[left] + data[right]*2;
father.areaR = data[left]*2 + data[right];
return father;
}*/
A son1 = new A();
A son2 = new A();
int mid = (father.left+father.right)/2;
son1.left = father.left;
son1.right = mid;
son2.left = mid+1;
son2.right = father.right;
father.son1 = create(data, son1.left, son1.right, son1);
father.son2 = create(data, son2.left, son2.right, son2);
father.hasSon = true;
father.areaSum = son1.areaSum + son2.areaSum;
father.areaL = son1.areaL + son2.areaL + son2.areaSum*(son2.left-son1.left);
father.areaR = son1.areaR + son2.areaR + son1.areaSum*(son2.right-son1.right);
return father;
}
// 参数increment是差值,在方法调用时传入
public void update(int i, int increment) {
if(i>this.right || i<this.left) {
return;
}
this.areaSum += increment;
this.areaL += increment*(i-this.left+1);
this.areaR += increment*(this.right-i+1);
if(this.hasSon) {
this.son1.update(i, increment);
this.son2.update(i, increment);
}
}
public int sumL(int x, int y) {
if(y<x) {
// not in this area
return 0;
}
if(x==this.left && y==this.right) {
// full case
return this.areaL;
}
if(y<this.son2.left) {
// full left
return this.son1.sumL(x, y);
}
if(x>this.son1.right) {
// full right
return this.son2.sumL(x, y);
}
int sum2 = this.son2.sum(son2.left, y);
int sumL1 = this.son1.sumL(x, son1.right);
int sumL2 = this.son2.sumL(son2.left, y);
return sumL1 + sumL2 + sum2*(son2.left-x);
}
public int sumR(int x, int y) {
if(y<x) {
// not in this area
return 0;
}
if(x==this.left && y==this.right) {
// full case
return this.areaR;
}
if(y<this.son2.left) {
// full left
return this.son1.sumR(x, y);
}
if(x>this.son1.right) {
// full right
return this.son2.sumR(x, y);
}
int sum1 = this.son1.sum(x, son1.right);
int sumR1 = this.son1.sumR(x, son1.right);
int sumR2 = this.son2.sumR(son2.left, y);
return sumR1 + sumR2 + sum1*(y-son1.right);
}
// sum of area(x,y)
private int sum(int x, int y) {
if(y<x) {
return 0;
}
if(x==this.left && y==this.right) {
return this.areaSum;
}
int sum1 = this.son1.sum(x, min(y,son1.right));
int sum2 = this.son2.sum(max(x,son2.left), y);
return sum1 + sum2;
}
// utils
private int max(int a, int b) {
return a>b?a:b;
}
private int min(int a, int b) {
return a<b?a:b;
}
}