/* *************************************************************** *\
|
| 基础线段树模板
| push_up(),build(),query()为基本线段树函数
| push_down()和update()函数用于成段更新
|
\* *************************************************************** */
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string.h>
using namespace std;
#define maxn 30000 //叶子节点数
#define Mid int mid=(left+right)>>1 //定义mid
#define lson rt*2,left,mid
#define rson rt*2+1,mid+1,right
int n,m; //n叶子节点数,m询问数
int node[maxn<<2]; //数组开maxn的四倍
int lazy[maxn<<2]; //懒惰标记
void push_up(int rt) //用于更新节点信息,修改时需要同时修改query()中返回值的处理机制,使二者统一(成段更新时还需修改push_down())
{
node[rt]=node[rt*2]+node[rt*2+1]; //这部分由线段树的作用(求和,求乘积,求最值......)决定
}
void push_down(int rt,int left ,int right) //懒惰标记下移一层
{
Mid;
lazy[rt*2]+=lazy[rt];
node[rt*2]=node[rt*2]+lazy[rt]*(mid-left+1);
lazy[rt*2+1]+=lazy[rt];
node[rt*2+1]=node[rt*2+1]+lazy[rt]*(right-mid);
lazy[rt]=0;
push_up(rt);
}
void build (int rt ,int left , int right ) //建树
{
if (left==right)
{
scanf("%d",&node[rt]);
return ;
}
Mid;
build (lson);
build(rson);
push_up(rt);
}
void update(int rt ,int left ,int right ,int l,int r,int c) //用于更新区间[left,right]的节点的值
{
if (l<=left&&right<=r)
{
lazy[rt]+=c;
node[rt]+=c*(right-left+1);
return ;
}
push_down(rt,left,right);
Mid;
if (l<=mid)
update(lson,l,r,c);
if (r>mid)
update(rson,l,r,c);
push_up(rt);
}
int query (int rt ,int left ,int right ,int l,int r)
{
if (l<=left&&right<=r)
{
return node[rt];
}
//push_down(rt,left,right); //成段更新时使用
Mid;
int ret=0;
if (l<=mid)
ret+=query(lson,l,r);
if (r>mid)
ret+=query(rson,l,r);
return ret;
}
int main()
{
int l,r,flg=0;
while (scanf("%d%d",&n,&m)!=EOF)
{
memset(node,0,sizeof (node));
memset(lazy,0,sizeof (lazy));
build(1,1,n);
for (int i=0;i<m;i++)
{
scanf("%d%d",&l,&r);
printf("%d\n",query(1,1,n,l,r) );
}
}
return 0;
}