您的位置:首页 > 编程语言 > Java开发

ccf 201709-5 除法 java

2018-03-13 22:53 176 查看
问题描述 
  小葱喜欢除法,所以他给了你N个数a1, a2, ⋯, aN,并且希望你执行M次操作,每次操作可能有以下两种: 
  给你三个数l, r, v,你需要将al, al+1, ⋯, ar之间所有v的倍数除以v。 
  给你两个数l, r,你需要回答al + al+1 + ⋯ + ar的值是多少。 
   
输入格式 
  第一行两个整数N, M,代表数的个数和操作的次数。 
  接下来一行N个整数,代表N个数一开始的值。输出格式 
  对于每一次的第二种操作,输出一行代表这次操作所询问的值。 
样例输入
5 3
1 2 3 4 5
2 1 5
1 1 3 2
2 1 5
1
2
3
4
5
样例输出
15
14
1
2
评测用例规模与约定 
  对于30%的评测用例,1 ≤ N, M ≤ 1000; 
  对于另外20%的评测用例,第一种操作中一定有l = r; 
  对于另外20%的评测用例,第一种操作中一定有l = 1 , r = N; 
  对于100%的评测用例,1 ≤ N, M ≤ 105,0 ≤ a1, a2, ⋯, aN ≤ 106, 1 ≤ v ≤ 106, 1 ≤ l ≤ r ≤ N。import java.util.Scanner;

public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();//n个数
int[] nums = new int[N+1];
long[] treeSum
4000
= new long[N+1];
int m = scanner.nextInt();//m次操作
for (int i = 1; i <=N; i++) {
nums[i] = scanner.nextInt();
add(treeSum,i,nums[i]);//构造树状数组

}

for (int i = 0; i < m; i++) {
int option = scanner.nextInt();
if (option==1){
int L =scanner.nextInt();
int r =scanner.nextInt();
int v =scanner.nextInt();
if (v!=1){//特别重要,没有这个判断会超时,只能得50分
for (int j = L; j <=r; j++) {
if(nums[j]>=v && nums[j]%v==0){
int value = nums[j] -nums[j]/v;
nums[j] = nums[j]/v;
add(treeSum,j,-value);
}
}
}

}else if(option==2){

int L = scanner.nextInt();
int r = scanner.nextInt();
long count = getSum(treeSum,r)-getSum(treeSum,L-1);
System.out.println(count);
}
}
}

private static long getSum(long[] treeNums, int n) {
long sum = 0 ;
while (n>0){
sum += treeNums
;
n -=lowbit(n);
}

return sum;

}

private static void add(long[] treeNums, int index,int value) {
if (index>0){
for (int i = index; i<=treeNums.length-1 ; i+=lowbit(i)) {
treeNums[i] +=value;
}
}

}
private static int lowbit(int value) {//lowbit(i) = 2^k
return value & (-value);
}
}

树状数组彻底入门

https://www.cnblogs.com/hsd-/p/6139376.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: