2017-09-05:除法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/han_hhh/article/details/82500339

返回试题列表

问题描述

试题编号: 201709-5
试题名称: 除法
时间限制: 10.0s
内存限制: 256.0MB
问题描述:

问题描述

  小葱喜欢除法,所以他给了你N个数a1, a2, ⋯, aN,并且希望你执行M次操作,每次操作可能有以下两种:
  给你三个数l, r, v,你需要将al, al+1, ⋯, ar之间所有v的倍数除以v
  给你两个数l, r,你需要回答al + al+1 + ⋯ + ar的值是多少。

输入格式

  第一行两个整数N, M,代表数的个数和操作的次数。
  接下来一行N个整数,代表N个数一开始的值。
  接下来M行,每行代表依次操作。每行开始有一个整数opt。如果opt=1,那么接下来有三个数l, r, v,代表这次操作需要将第l个数到第r个数中v的倍数除以v;如果opt = 2,那么接下来有两个数l, r,代表你需要回答第l个数到第r个数的和。

输出格式

  对于每一次的第二种操作,输出一行代表这次操作所询问的值。

样例输入

5 3
1 2 3 4 5
2 1 5
1 1 3 2
2 1 5

样例输出

15
14

评测用例规模与约定

  对于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 ≤ lrN

在树状数组的模板上修改而成,要注意数据范围,以及v==1时的情况

90分,运行超时。看树状数组看的有点晕了,找不出来问题,一会再继续找

#include<iostream>
#include<cstdio>

using namespace std;

typedef long long LL;

const int maxn=101024;

LL tree[maxn];
int a[maxn];
LL lowbit(int x)
{
    return x&(-x);
}
//修改操作
void change(int x,int h)
{
    for(int i=x;i<=maxn;i+=lowbit(i)){
        tree[i]+=h;
    }
}
//查询操作
LL getsum(int x)
{
    LL res=0;
    while(x>0){
        res+=tree[x];
        x-=lowbit(x);
    }
    return res;
}

int main()
{
    int n,m,opt;
    scanf("%d%d",&n,&m);//区间长度和询问次数
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);//输入第i个位置的数
        change(i,a[i]);//从第i位进行修改树状数组
    }
    while(m--){
        LL l,r,v;
        cin>>opt>>l>>r;
        if(opt==1){
            cin>>v;
            if(v==1)
                continue;
            while(l<=r){
                if(a[l]>=v&&a[l]%v==0){
                    change(l,-(a[l]-a[l]/v));
                    a[l]/=v;
                }
                ++l;
            }
         }


        else if(opt==2){
            printf("%lld\n",getsum(r)-getsum(l-1));//询问[1,temp]区间的和
        }
}

    return 0;
}

猜你喜欢

转载自blog.csdn.net/han_hhh/article/details/82500339
今日推荐