NC23054 华华开始学信息学

在这里插入图片描述
思路:
分块,树状数组
直接树状数组进行add操作
for(int i=d;i<=n;i+=d))add(d,k)
时间复杂度起码是O(nm)=1e10,肯定t
这个时候我们可以考虑进行分块操作
对于d小于等于√n的我们就存到一个lazy数组里
大于√n的我们就直接进行树状数组的add操作
这样的话根据上面那个循环我们add操作时间复杂度差不多是log2(n)(树状数组本身add操作为logn)
而lazy操作为O1
查询区间和的时候
lazy操作为logn(直接扫一遍下标小于logn的数)
得树状数组和也为logn
这样就能大大优化时间复杂度得到答案了

AC代码:

#include <iostream>
#include <math.h>
#define IOS ios::sync_with_stdio(false);
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll a[N];
ll lazy[N];
ll c[N];
int n,m;
int lower_bit(int x)
{
    return x&(-x);
}
ll getsum(int x)
{
    ll cnt=0;
    while(x>0)
    {
        cnt+=c[x];
        x-=lower_bit(x);
    }
    return cnt;
}
void add(int x,ll k)
{
    while(x<=n)
    {
        c[x]+=k;
        x+=lower_bit(x);
    }
    return;
}
int main()
{
    IOS;
    cin>>n>>m;
    while(m--)
    {
        int q;
        cin>>q;
        if(q==1)
        {
            int d,k;
            cin>>d>>k;
            if(d<=sqrt(n))
            {
                lazy[d]+=k;
            }
            else
            {
                for(int i=1; i*d<=n; i++) //logn时间复杂度
                {
                    add(d*i,k);
                }
            }
        }
        else
        {
            int l,r;
            cin>>l>>r;
            ll ans=getsum(r)-getsum(l-1);
            for(int i=1; i<=sqrt(n); i++) //logn时间复杂度
            {
                ans+=(r/i-(l-1)/i)*lazy[i];
            }
            cout<<ans<<endl;
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值