zoukankan      html  css  js  c++  java
  • loj #6277. 数列分块入门 1

    #6277. 数列分块入门 1

    题目描述

    给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及区间加法,单点查值。

    输入格式

    第一行输入一个数字 nnn。

    第二行输入 nnn 个数字,第 iii 个数字为 aia_iai​​,以空格隔开。

    接下来输入 nnn 行询问,每行输入四个数字 optmathrm{opt}opt、lll、rrr、ccc,以空格隔开。

    opt=0mathrm{opt} = 0opt=0,表示将位于 [l,r][l, r][l,r] 的之间的数字都加 ccc。

    opt=1mathrm{opt} = 1opt=1,表示询问 ara_rar​​ 的值(lll 和 ccc 忽略)。

    输出格式

    对于每次询问,输出一行一个数字表示答案。

    样例

    样例输入

    4
    1 2 2 3
    0 1 3 1
    1 0 1 0
    0 1 2 2
    1 0 2 0

    样例输出

    2
    5

    数据范围与提示

    对于 100% 100\% 100% 的数据,1≤n≤50000,−231≤others 1 leq n leq 50000, -2^{31} leq mathrm{others}1n50000,231​​others、ans≤231−1 mathrm{ans} leq 2^{31}-1 ans231​​1。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 50010
    using namespace std;
    int n,sum[maxn*4],lazy[maxn*4];
    void build(int k,int l,int r){
        if(l==r){
            scanf("%d",&sum[k]);
            return;
        }
        int mid=(l+r)>>1;
        build(k<<1,l,mid);build(k<<1|1,mid+1,r);
        sum[k]=sum[k<<1]+sum[k<<1|1];
    }
    void pushdown(int k,int l,int r){
        if(!lazy[k])return;
        int mid=(l+r)>>1;
        lazy[k<<1]+=lazy[k];sum[k<<1]+=lazy[k]*(mid-l+1);
        lazy[k<<1|1]+=lazy[k];sum[k<<1|1]+=lazy[k]*(r-mid);
        lazy[k]=0;
    }
    void modify(int k,int l,int r,int opl,int opr,int opv){
        if(l>=opl&&r<=opr){
            lazy[k]+=opv;
            sum[k]+=opv*(r-l+1);
            return;
        }
        pushdown(k,l,r);
        int mid=(l+r)>>1;
        if(opl<=mid)modify(k<<1,l,mid,opl,opr,opv);
        if(opr>mid)modify(k<<1|1,mid+1,r,opl,opr,opv);
        sum[k]=sum[k<<1]+sum[k<<1|1];
    }
    int query(int k,int l,int r,int opx){
        if(l==r)return sum[k];
        pushdown(k,l,r);
        int mid=(l+r)>>1,res;
        if(opx<=mid)res=query(k<<1,l,mid,opx);
        else res=query(k<<1|1,mid+1,r,opx);
        sum[k]=sum[k<<1]+sum[k<<1|1];
        return res;
    }
    int main(){
        scanf("%d",&n);
        build(1,1,n);
        int op,l,r,c;
        for(int i=1;i<=n;i++){
            if(i==3){
                int x=1;
            }
            scanf("%d%d%d%d",&op,&l,&r,&c);
            if(op==0)modify(1,1,n,l,r,c);
            else printf("%d
    ",query(1,1,n,r));
        }
        return 0;
    }
    线段树区间修改+单点查询
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define maxn 50010
    using namespace std;
    int n,block,a[maxn],b[maxn],pos[maxn];
    void update(int l,int r,int c){
        for(int i=l;i<=min(pos[l]*block,r);i++)a[i]+=c;
        if(pos[l]!=pos[r])
            for(int i=(pos[r]-1)*block+1;i<=r;i++)
            a[i]+=c;
        for(int i=pos[l]+1;i<=pos[r]-1;i++)b[i]+=c;
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        block=sqrt(n);
        for(int i=1;i<=n;i++)pos[i]=(i-1)/block+1;
        int op,l,r,c;
        for(int i=1;i<=n;i++){
            scanf("%d%d%d%d",&op,&l,&r,&c);
            if(op==0)update(l,r,c);
            else printf("%d
    ",a[r]+b[pos[r]]);
        }
        return 0;
    }
    分块
  • 相关阅读:
    初识函数定义与调用 * 和 **
    文件操作
    小程序缓存数据
    调用外部的方法
    小程序订单的待付款实现倒计时(秒)
    小程序上线流程
    微信小程序点击保存图片到相册
    修改头像
    点击保存图片
    小程序的学习王战
  • 原文地址:https://www.cnblogs.com/thmyl/p/8961260.html
Copyright © 2011-2022 走看看