BUPT Summer Journey #test8 E

来源:互联网 发布:机房网络布线方案 编辑:程序博客网 时间:2024/05/17 22:09

 

E. 田田的算数题 2014新生暑假个人排位赛08

时间限制 10000 ms    内存限制 65536 KB    

题目描述

焦级长和田田玩算数。焦级长给田田一个数列ai,然后问田田第i项到第j项的数的和。
田田随手写了个简单的数据结构就搞定了。于是焦级长打算加大题目难度。
焦级长又添加了一个操作,即从第i项到第j项都按顺序加上一个等差数列的项
如从第2项到第4项加入一个首项为1,公差为3的等差数列即第2项+1,第3项+4,第4项+7,以此类推
于是田田写了半天又WA又T还RE了一炮,终于来求救你让你来写个程序帮他

 

输入格式

第一行为case数T
每个case第一行输入n,m,表示有数列长为n,有m个操作
之后n个数为ai即数列的初始数
之后m行为m个操作
第一个操作为插入
为1,l,r,x,d
1表示插入操作,l,r为数列的[l,r]会进行操作,等差数列的首项为x,公差为d
第二个操作为查询和
为2,l,r
2表示查询,l,r为求和的范围,即求al到ar的数列的和

T<=10
n,m<=10^5
ai,x<10^5,|d|<=100;

输出格式

每个查询输出一个值

输入样例

16 91 2 3 4 5 62 1 42 1 61 1 4 1 02 2 51 2 4 1 12 1 42 2 42 1 52 2 6

输出样例

10211720182529

 

思路:其实有了首项与公差,整个区间的和就知道了。只需要两个域记录这个区间的首项与公差即可。

代码:

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#define maxn 1000005//#define LOCALusing namespace std;int n,m;long long a[maxn],sum[maxn<<2],sumo[maxn<<2],addv[maxn<<2],setv[maxn<<2];void build(int o,int L,int R){    //printf("L=%d R=%d\n",L,R);    int lc=o<<1,rc=(o<<1)+1;    addv[o]=setv[o]=0;    if(L==R){sum[o]=sumo[o]=a[L];return;}    int M=(L+R)>>1;    build(lc,L,M);    build(rc,M+1,R);    sum[o]=sum[lc]+sum[rc];    //printf("0 o=%d L=%d R=%d sum=%I64d setv1=%I64d setv2=%I64d\n",o,L,R,sumv[o],setv1[o],setv2[o]);}void maintain(int o,int L,int R){    int lc=o<<1,rc=(o<<1)+1;    sum[o]=0;    if(L==R)sum[o]=sumo[o];    if(L<R)sum[o]=sum[lc]+sum[rc];    sum[o]+=addv[o]*(R-L+1);    sum[o]+=(R-L+1)*(R-L)/2*setv[o];}void update(int o,int L,int R,int l,int r,long long v,long long d){    //printf("1 o=%d L=%d R=%d l=%d r=%d v=%I64d d=%I64d\n",o,L,R,l,r,v,d);    int lc=o<<1,rc=(o<<1)+1;    if(l<=L&&R<=r)    {        addv[o]+=(v+(L-l)*d);        setv[o]+=d;    }    else    {        int M=(L+R)>>1;        if(l<=M)update(lc,L,M,l,r,v,d);        if(M<r)update(rc,M+1,R,l,r,v,d);    }    maintain(o,L,R);    //printf("2 o=%d L=%d R=%d l=%d r=%d v=%I64d d=%I64d\n",o,L,R,l,r,v,d);    //printf("sum=%I64d addv=%I64d setv=%I64d\n",sum[o],addv[o],setv[o]);}long long query(int o,int L,int R,int l,int r,long long add,long long set){    long long ret=0;    int lc=o<<1,rc=(o<<1)+1;    //printf("3 o=%d L=%d R=%d l=%d r=%d add=%I64d set=%I64d\n",o,L,R,l,r,add,set);    if(l<=L&&R<=r)    {        //printf("sumo=%I64d\n",sum[o]);        ret+=(sum[o]+add*(R-L+1)+(R-L)*(R-L+1)/2*set);    }    else    {        int M=(L+R)>>1;        if(l<=M)ret+=query(lc,L,M,l,r,add+addv[o],set+setv[o]);        if(M<r)        {            //printf("3.5 o=%d L=%d R=%d l=%d r=%d add=%I64d set=%I64d\n",o,L,R,l,r,add,set);            //printf("3.5 o=%d M+1=%d R=%d l=%d r=%d add=%I64d set=%I64d\n",o,M+1,R,l,r,add,set);            //printf("3.5 %I64d %I64d\n",addv[o],setv[o]);            ret+=query(rc,M+1,R,l,r,add+addv[o]+(M-L+1)*(set+setv[o]),set+setv[o]);        }    }    //printf("4 o=%d L=%d R=%d l=%d r=%d add=%I64d set=%I64d\n",o,L,R,l,r,add,set);    //printf("4 ret=%I64d\n",ret);    return ret;}int main(){    #ifdef LOCAL    freopen("input.txt","r",stdin);    #endif // LOCAL    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        for(int i=1;i<=n;i++)scanf("%lld",&a[i]);        build(1,1,n);        long long kind,l,r,x,d;        for(int i=1;i<=m;i++)        {            scanf("%lld",&kind);            if(kind==1)            {                scanf("%lld%lld%lld%lld",&l,&r,&x,&d);                update(1,1,n,l,r,x,d);            }            if(kind==2)            {                scanf("%lld%lld",&l,&r);                printf("%lld\n",query(1,1,n,l,r,0,0));            }        }    }    return 0;}


 

0 0
原创粉丝点击