ccf 201709-5 除法 java

问题描述 
  小葱喜欢除法,所以他给了你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 = 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];
            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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值