无聊的数列【线段树】

题目描述

维护一个数列{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\n",a[x]+qur(1,1,n,1,x));
        }
    }
    return 0;
}

 

posted @ 2018-11-02 17:50  qseer  阅读(163)  评论(0编辑  收藏  举报