• 【洛谷 2068】统计和


    题目描述

    给定一个长度为n(n<=100000),初始值都为0的序列,x(x<=10000)次的修改某些位置上的数字,每次加上一个数,然后提出y (y<=10000)个问题,求每段区间的和。时间限制1秒。

    输入输出格式

    输入格式:

    第一行1个数,表示序列的长度n

    第二行1个数,表示操作的次数w

    后面依次是w行,分别表示加入和询问操作

    其中,加入用x表示,询问用y表示

    x的格式为"x a b" 表示在序列a的位置加上b

    y的格式为"y a b" 表示询问a到b区间的加和

    输出格式:

    每行一个数,分别是每次询问的结果

    输入输出样例

    输入样例#1: 复制
    5
    4
    x 3 8
    y 1 3
    x 4 9
    y 3 4
    输出样例#1: 复制
    8
    17

    线段数做法:
    // luogu-judger-enable-o2
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #define maxn 100007 
    using namespace std;
    int n,m,x,y,z;
    char jjj[4];
    long long Sum[maxn<<2],Add[maxn<<2];
    int A[maxn];
    
    void PushUp(int rt){Sum[rt]=Sum[rt*2]+Sum[rt*2+1];}
    
    void Build(int l,int r,int rt){
        if(l==r) {
            Sum[rt]=A[l];
            return;
        }
        int m=(l+r)>>1;
        Build(l,m,rt<<1);
        Build(m+1,r,rt<<1|1);
        PushUp(rt);
    }
    void PushDown(int rt,int ln,int rn){
        if(Add[rt]){
            Add[rt<<1]+=Add[rt];
            Add[rt<<1|1]+=Add[rt];
            Sum[rt<<1]+=Add[rt]*ln;
            Sum[rt<<1|1]+=Add[rt]*rn;
            Add[rt]=0;
        }
    }
    long long Query(int L,int R,int l,int r,int rt){
        if(L <= l && r <= R)
            return Sum[rt];
        int m=(l+r)>>1;
        PushDown(rt,m-l+1,r-m); 
        long long ANS=0;
        if(L <= m) ANS+=Query(L,R,l,m,rt<<1);
        if(R >  m) ANS+=Query(L,R,m+1,r,rt<<1|1);
        return ANS;
    } 
    
    void Update(int L,int R,int C,int l,int r,int rt){
        if(L <= l && r <= R){
            Sum[rt]+=C*(r-l+1);
            Add[rt]+=C;
            return ; 
        }
        int m=(l+r)>>1;
        PushDown(rt,m-l+1,r-m);
        if(L <= m) Update(L,R,C,l,m,rt<<1);
        if(R >  m) Update(L,R,C,m+1,r,rt<<1|1); 
        PushUp(rt);
    } 
    
    int main(){
        while(scanf("%d%d",&n,&m)!=EOF){
            for(int i=1;i<=n;i++)
                A[i]=0;
            Build(1,n,1);
            while(m--)
            {
                scanf("%s",jjj);
                if(jjj[0]=='x') {
                    scanf("%d%d",&x,&z);
                    Update(x,x,z,1,n,1);
                }
                else {
                    scanf("%d%d",&x,&y);
                    printf("%lld
    ",Query(x,y,1,n,1));
                }
            }
        }
        return 0;
    }

    树状数组解法如下:

    #include<iostream>
    using namespace std;
    const int MAXN=100000+2;
    int a[MAXN];
    int n,w;
    int lowbit(int x){
        return x&(-x);
    }
    void add(int p,int x){
        while(p<=n){
            a[p]+=x;
            p+=lowbit(p);
        }
    }
    int ask(int p){
        int ans=0;
        while(p>0){
            ans+=a[p];
            p-=lowbit(p);
        }
        return ans;
    }
    int main(){
        cin>>n>>w;
        for(int i=1;i<=w;i++){
            char q;
            int y,z;
            cin>>q>>y>>z;
            if(q=='x') add(y,z);
            else cout<<ask(z)-ask(y-1)<<endl;
        }
        return 0;
    }


  • 相关阅读:
    linux学习之用户的切换
    Skyline桌面二次开发之路径漫游(C#)
    AppDomain.CurrentDomain.BaseDirectory项目目录相关操作
    IoC模式(依赖、依赖倒置、依赖注入、控制反转)
    .net core 2.1-----Sql Server数据库初体验
    WPF成长之路------翻转动画
    C#之通过图片地址下载图片
    g'g'gggg
    Java中的多态
    接口
  • 原文地址:https://www.cnblogs.com/wuhu-JJJ/p/11205996.html
Copyright © 2020-2023  润新知