zoukankan      html  css  js  c++  java
  • 牛客小白月赛12 F 华华开始学信息学 (分块+树状数组)

    链接:https://ac.nowcoder.com/acm/contest/392/F
    来源:牛客网

    时间限制:C/C++ 2秒,其他语言4秒
    空间限制:C/C++ 32768K,其他语言65536K
    64bit IO Format: %lld
    题目描述
    因为上次在月月面前丢人了,所以华华决定开始学信息学。十分钟后,他就开始学树状数组了。这是一道树状数组的入门题:
    给定一个长度为N的序列A,所有元素初值为0。接下来有M次操作或询问:
    操作:输入格式:1 D K,将A_DA
    D

    加上K。
    询问:输入格式:2 L R,询问区间和,即sum_{i=L}^{R}A_i∑
    i=L
    R

    A
    i


    华华很快就学会了树状数组并通过了这道题。月月也很喜欢树状数组,于是给华华出了一道进阶题:
    给定一个长度为N的序列A,所有元素初值为0。接下来有M次操作或询问:
    操作:输入格式:1 D K,对于所有满足1le ile N1≤i≤N且iequiv0(mod D)i≡0(modD)的i,将A_iA
    i

    加上K。
    询问:输入格式:2 L R,询问区间和,即sum_{i=L}^{R}A_i∑
    i=L
    R

    A
    i


    华华是个newbie,怎么可能会这样的题?不过你应该会吧。
    输入描述:
    第一行两个正整数N、M表示序列的长度和操作询问的总次数。
    接下来M行每行三个正整数,表示一个操作或询问。
    输出描述:
    对于每个询问,输出一个非负整数表示答案。
    示例1
    输入
    复制
    10 6
    1 1 1
    2 4 6
    1 3 2
    2 5 7
    1 6 10
    2 1 10
    输出
    复制
    3
    5
    26
    备注:
    1le N,Mle10^51≤N,M≤10
    5
    ,1le Dle N1≤D≤N,1le Lle Rle N1≤L≤R≤N,1le K le 10^81≤K≤10
    8

    思路:

    这里我用 laze[i] 代表 i的倍数被加多少值

    询问的时候暴力扫1~sqrtn 的laze,同时用数论分块可以知道 区间中i的倍数有多少个,计算贡献即可。

    推荐博客:https://www.cnblogs.com/zjl192628928/p/10544105.html

    细节见代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <vector>
    #include <iomanip>
    #define ALL(x) (x).begin(), (x).end()
    #define sz(a) int(a.size())
    #define all(a) a.begin(), a.end()
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define pii pair<int,int>
    #define pll pair<long long ,long long>
    #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define MS0(X) memset((X), 0, sizeof((X)))
    #define MSC0(X) memset((X), '', sizeof((X)))
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define eps 1e-6
    #define gg(x) getInt(&x)
    #define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
    using namespace std;
    typedef long long ll;
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
    ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;}
    inline void getInt(int* p);
    const int maxn = 100010;
    const int inf = 0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    ll tree[maxn];
    int n;
    int lowbit(int x)
    {
        return x & (-1 * x);
    }
    void add(int x, ll val)
    {
        while (x <= n)
        {
            tree[x] += val;
            x += lowbit(x);
        }
    }
    ll ask(int x)
    {
        ll res = 0ll;
        while (x)
        {
            res += tree[x];
            x -= lowbit(x);
        }
        return res;
    }
    ll laze[maxn];
    // ll n;
    int main()
    {
        //freopen("D:\common_text\code_stream\in.txt","r",stdin);
        //freopen("D:\common_text\code_stream\out.txt","w",stdout);
        int m;
        scanf("%d", &n);
        scanf("%d", &m);
        int blocks=(int)(sqrt(n)+0.5);
        while(m--)
        {
            int op,l,r;
            scanf("%d %d %d",&op,&l,&r);
            if(op==1)
            {
                if(l>=blocks)
                {
                    for(int i=l;i<=n;i+=l)
                    {
                        add(i,1ll*r);
                    }
                }else
                {
                    laze[l]+=r;
                }
            }else
            {
                ll ans=ask(r)-ask(l-1);
                repd(i,1,blocks)
                {
                    ans+=laze[i]*(r/i-(l-1)/i);
                }
                printf("%lld
    ",ans );
            }
        }
    
        return 0;
    }
    
    inline void getInt(int* p) {
        char ch;
        do {
            ch = getchar();
        } while (ch == ' ' || ch == '
    ');
        if (ch == '-') {
            *p = -(getchar() - '0');
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 - ch + '0';
            }
        }
        else {
            *p = ch - '0';
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 + ch - '0';
            }
        }
    }
    
    
    
    
    
    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    LocalDateTime方法plusHours()
    windows查看所有端口, 查看端口是否占用
    maven编译引起excel文件损坏问题解决
    Java BigDecimal 添加数据
    postgresql数据库设置联合主键的语句
    Linux为普通用户挂载磁盘
    Glog不打印错误方法
    关闭书莓派3B所有指示灯
    巧用Python自带http服务实现文件共享
    VIM高阶使用技巧
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/11421197.html
Copyright © 2011-2022 走看看