zoukankan      html  css  js  c++  java
  • ACM-ICPC 2018 徐州赛区网络预赛 HRyuji doesn't want to study 树状数组

    题目链接:https://nanti.jisuanke.com/t/A2007

    题目大意:有一个序列含有n个数a[1],a[2],a[3],……a[n],有两种操作:

    第一种操作:k=1,l,r,询问区间[l,r]中a[l]*len+a[l+1]*(len-1)+a[l+2]*(len-2)……+a[r]*1,其中len=(r-l+1),即区间长度

    第二种操作:k=2,  l,r将下标为l的值a[l]修改为r

    一共有q个询问,对于每个询问,如果k==1,输出答案即可。

    解题思路:先进行一个小小的推理

    询问可以简化为这种形式:

    ans=Σ(i=l->r) (r+1-i)*a[i],然后可转化成,ans=Σ(i=l->r) (r+1)*a[i]-Σ(i=l->r) i*a[i]

    然后就变成一个很简单的树状数位维护前缀和问题了,即为前缀和a【i】和i*a【i】就好了

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+5;
    int n,q;
    ll sum1[maxn],sum2[maxn];
    int lowbit(int x){return x&(-x);}
    void update(ll a[],int x,ll val){
        while(x<=maxn){
            a[x]+=val;
            x+=lowbit(x);
        }
    }
    ll ask(ll a[],int x){
        ll res=0;
        while(x){
            res+=a[x];
            x-=lowbit(x);
        }
        return res;
    }
    int main(){
        cin>>n>>q;
        for(int i=1;i<=n;i++){
            ll val;
            cin>>val;
            update(sum1,i,val);
            update(sum2,i,i*val);
        }
        while(q--){
            ll k,x,y;
            cin>>k>>x>>y;
            if(k==1){
                cout<<(y+1)*(ask(sum1,y)-ask(sum1,x-1))-(ask(sum2,y)-ask(sum2,x-1))<<endl;
            }else{
                ll num=ask(sum1,x)-ask(sum1,x-1);
                update(sum1,x,y-num);
                num=ask(sum2,x)-ask(sum2,x-1);
                update(sum2,x,x*y-num);
            }
        }
        return 0;
    }
  • 相关阅读:
    暗时间:学习的精神和方法
    林布蘭
    魯本斯
    維梅爾
    哈爾斯.法蘭斯
    SAFEARRAY使用方法示例
    范戴克
    100个经典错别字
    在CPP中调用Jscript中的函数
    生活在真空中的程序员
  • 原文地址:https://www.cnblogs.com/zjl192628928/p/10665496.html
Copyright © 2011-2022 走看看