• 无聊的数列【线段树】


    题目描述

    维护一个数列{a[i]},支持两种操作:

    1、1 L R K D:给出一个长度等于R-L+1的等差数列,首项为K,公差为D,并将它对应加到a[L]~a[R]的每一个数上。即:令a[L]=a[L]+K,a[L+1]=a[L+1]+K+D,

    a[L+2]=a[L+2]+K+2D……a[R]=a[R]+K+(R-L)D。

    2、2 P:询问序列的第P个数的值a[P]。

    输入输出格式

    输入格式:

     

    第一行两个整数数n,m,表示数列长度和操作个数。

    第二行n个整数,第i个数表示a[i](i=1,2,3…,n)。

    接下来的m行,表示m个操作,有两种形式:

    1 L R K D

    2 P 字母意义见描述(L≤R)。

     

    输出格式:

     

    对于每个询问,输出答案,每个答案占一行。

     

    输入输出样例

    输入样例
    5 2
    1 2 3 4 5
    1 2 4 1 2
    2 3
    
    输出样例
    6

    说明

    数据规模:

    0≤n,m≤100000

    |a[i]|,|K|,|D|≤200


    神奇的线段树,本来线段树的用法都是静态地操作,现在发现连这样的动态的等差数列都可以添加

    其实关键是利用了差分的原理,通过线段树可以很好地发挥差分的优势

    code

    #include<stdio.h> 
    #include<algorithm> 
    #define ls x<<1
    #define rs x<<1|1
    using namespace std;
    const int mxn=100010;
    int n,m,K,D;
    int a[mxn],laz[mxn<<2],tree[mxn<<2];
    
    inline int In() {
        int s=0,f=1;
        char ch=getchar();
        while(ch>'9' || ch<'0') {
            if(ch=='-') f=-1;
            ch=getchar();
        }
        while(ch>='0' && ch<='9') s=s*10+ch-'0',ch=getchar();
        return s*f;
    }
    
    void pd(int x,int l,int r,int mid) {
        if(laz[x]) {
            laz[ls]+=laz[x];
            laz[rs]+=laz[x];
            tree[ls]+=(mid-l+1)*laz[x];
            tree[rs]+=(r-mid)*laz[x];
            laz[x]=0;
        }
    }
    
    void add(int x,int l,int r,int ql,int qr,int val) 
    {
        if(ql<=l && qr>=r) {
            tree[x]+=val*(r-l+1),laz[x]+=val;
            return ;
        }
        int mid=(l+r)>>1;
        pd(x,l,r,mid);
        if(ql<=mid) add(ls,l,mid,ql,qr,val);
        if(qr>mid) add(rs,mid+1,r,ql,qr,val);
        tree[x]=tree[ls]+tree[rs];
    }
    
    int qur(int x,int l,int r,int ql,int qr)  
    {
        if(ql<=l && qr>=r) return tree[x];
        int mid=(l+r)>>1,re=0;
        pd(x,l,r,mid);
        if(ql<=mid) re+=qur(ls,l,mid,ql,qr);
        if(qr>mid) re+=qur(rs,mid+1,r,ql,qr);
        return re;
    }
    
    int main() 
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) scanf("%d",&a[i]);
        for(int i=1;i<=m;++i) {
            int cas;
            scanf("%d",&cas);
            if(cas==1) {
                int ql,qr;
                scanf("%d%d%d%d",&ql,&qr,&K,&D);
                add(1,1,n,ql,ql,K);
                if(qr>ql) add(1,1,n,ql+1,qr,D);
                if(qr!=n) add(1,1,n,qr+1,qr+1,-K-(qr-ql)*D);
            }
            else if(cas==2) {
                int x;
                scanf("%d",&x);
                printf("%d
    ",a[x]+qur(1,1,n,1,x));
            }
        }
        return 0;
    }
  • 相关阅读:
    10个值得我们关注的python博客
    Python获取并修改hosts
    详解python2 和 python3的区别
    Python监控网站运行状况
    用Flask实现视频数据流传输
    Python框架 Flask 项目实战教程
    使用Flask设计带认证token的RESTful API接口[翻译]
    使用python的Flask实现一个RESTful API服务器端[翻译]
    使用单用户模式破解Linux密码
    Linux软件的安装与卸载
  • 原文地址:https://www.cnblogs.com/qseer/p/9897575.html
Copyright © 2020-2023  润新知