• CodeChef


    https://vjudge.net/problem/CodeChef-FNCS

    题意

    思路

    用分块的方法,对每个函数进行分块,计算出该分块里每个数的个数,这样的话也就能很方便的计算出这个分块里所有数的和。

    用树状数组维护数组的话可以很方便的计算出某个区间内所有数的和以及修改某个数。

    每次查询时,如果在中间块的函数,我们直接加上sum[i](sum[i]为预处理的每一块的和),对于两边的函数,就用树状数组快速求一下和即可。

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<cmath>
    #include<map>
    #include<set>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    const int INF = 0x3f3f3f3f;
    const int maxn = 1e5+5;
    
    int n , m, unit, num;
    int a[maxn],l[maxn],r[maxn];
    int cnt[400][maxn];
    ll c[maxn],sum[maxn];
    
    int lowbit(int x)
    {
        return x&-x;
    }
    
    ll getsum(int x)
    {
        ll ret = 0;
        while(x>0)
        {
            ret+=c[x];
            x-=lowbit(x);
        }
        return ret;
    }
    
    int add(int x, int d)
    {
        while(x<=n)
        {
            c[x]+=d;
            x+=lowbit(x);
        }
    }
    
    void update(int x, int y)
    {
        add(x,y-a[x]);
        for(int i=1;i<=num;i++)  sum[i]+=(ll)cnt[i][x]*(y-a[x]);
        a[x]=y;
    }
    
    ll query(int left, int right)
    {
        ll ans = 0;
        int l_unit=(left-1)/unit+1,r_unit=(right-1)/unit+1;
        if(l_unit==r_unit)
        {
            for(int i=left;i<=right;i++)
                ans+=getsum(r[i])-getsum(l[i]-1);
        }
        else
        {
            for(int i=l_unit+1;i<r_unit;i++)  ans+=sum[i];
            for(int i=left;i<=(l_unit)*unit;i++)  ans+=getsum(r[i])-getsum(l[i]-1);
            for(int i=(r_unit-1)*unit+1;i<=right;i++) ans+=getsum(r[i])-getsum(l[i]-1);
        }
        return ans;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        scanf("%d",&n);
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++)  {scanf("%d",&a[i]);add(i,a[i]);}
        for(int i=1;i<=n;i++)  scanf("%d%d",&l[i],&r[i]);
    
    
        unit = (int)sqrt(n+0.5);
        num = unit + (unit*unit!=n);
        int now = 0;
        for(int i=1;i<=n;i++)
        {
            if(i%unit==1)  now++;
            cnt[now][l[i]]++;
            cnt[now][r[i]+1]--;
        }
    
        for(int i=1;i<=num;i++)
        {
            for(int j=1;j<=n;j++)
            {
                cnt[i][j]+=cnt[i][j-1];
                sum[i]=sum[i]+(ll)cnt[i][j]*a[j];
            }
        }
    
        scanf("%d",&m);
        while(m--)
        {
            int op, x, y;
            scanf("%d%d%d",&op,&x,&y);
            if(op==1) update(x,y);
            else printf("%lld
    ",query(x, y));
        }
        return 0;
    }
    

      

  • 相关阅读:
    hmset
    java 调用mongo 判断大于等于 并且小约等于<=
    Maven项目,别人的没问题,自己机器一直有问题
    linux 时间datetimectl 问题
    真正手把手教 git
    0324-SQLMAP使用参数备注
    安全推荐网址:
    JavaScript Base64 作为文件上传的实例代码解析
    学习笔记|变量的解构赋值
    学习笔记|let 和 const 命令
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7703785.html
Copyright © 2020-2023  润新知