洛谷oj 3372
题目描述
如题,已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数加上x
2.求出某区间每一个数的和
输入输出格式
输入格式:
第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k
操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和
输出格式:
输出包含若干行整数,即为所有操作2的结果。
输入输出样例
输入样例#1:
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
输出样例#1:
11
8
20
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
(数据已经过加强^_^,保证在int64/long long数据范围内)
我们发现就是一道裸题。。。。
而且没有区间修改,但是我还是写了个range。。。
易错点:不要写update 直接在pushdown中写对其左右子节点的操作。
else if 一定记得写else。。。。。。
最后是在get中要设置k来记录最后+k查询
下面上代码,,,
#include<bits/stdc++.h>
#define LL long long
using namespace std;
struct lll{
LL l;
LL r;
lll *ls;
lll *rs;
LL sum;
LL tag;
// lll(){sum=0;tag=-1;}
};
lll rt;
lll *rtt=&rt;
LL m,n,x[1000005]/*,tsyrq[1000][1000]*/;
LL read()
{
LL n=0;
char ch=getchar();
while(ch>'9'||ch<'0') ch=getchar();
while(ch<='9'&&ch>='0')
{
n=n*10+ch-'0';
ch=getchar();
}
return n;
}
void bulid(lll *p,LL l,LL r)
{
p->l=l;p->r=r;p->tag=0;p->sum=0;
if(l+1==r)
{p->sum=x[l];
return ;
}
if(l+1<r)
{
LL mid=(l+r)>>1;
lll *ll=new lll;
p->ls=ll;
bulid(p->ls,l,mid);
p->sum+=p->ls->sum;
lll *rr=new lll;
p->rs=rr;
bulid(p->rs,mid,r);
p->sum+=p->rs->sum;
}
}
void change(lll *p,LL pos,LL pp)
{
p->sum+=pp;
if(p->l+1 < p->r)
{
LL mid=(p->l+p->r)>>1;
if(pos<mid)
{
change(p->ls,pos,pp);
}
else
{
change(p->rs,pos,pp);
}
}
}
void pushdown(lll *p)
{
if(p->tag!=0)
{
p->ls->sum+=p->tag*(p->ls->r-p->ls->l);
p->ls->tag+=p->tag;
p->rs->sum+=p->tag*(p->rs->r-p->rs->l);
p->rs->tag+=p->tag;
p->tag=0;
}
}
void add(lll *p , LL l , LL r , LL pp)
{ p->sum+=pp*(r-l);
if(p->r==r&&p->l==l)
{
p->tag+=pp;
}
else
{
pushdown(p);
LL mid=(p->r+p->l)>>1;
if(r<=mid)
add(p->ls,l,r,pp);
else if(l>=mid)
add(p->rs,l,r,pp);
else
{
add(p->ls,l,mid,pp);
add(p->rs,mid,r,pp);
}
}
}
void range(lll *p,LL l,LL r ,LL pp)
{
if(p->r==r&&p->l==l)
{
p->tag=pp;
update(p);
}
else
{
pushdown(p);
LL mid=(p->r+p->l)>>1;
if(r<=mid)
range(p->ls,l,r,pp);
else if(l>=mid)
range(p->rs,l,r,pp);
else
{
range(p->ls,l,mid,pp) ;
range(p->rs,mid,r,pp) ;
}
update(p);
}
}
LL getsum(lll *p,LL l,LL r)
{
if(p->l==l&&p->r==r)
return p->sum;
else{
LL k=p->tag*(r-l);
int mid=(p->r+p->l)>>1;
if(r<=mid)
return getsum(p->ls,l,r)+k;
else if(l>=mid)
return getsum(p->rs,l,r)+k;
else
return getsum(p->ls,l,mid)+k+getsum(p->rs,mid,r);
}
}
int main()
{
n=read();
m=read();
for(int i=1;i<=n;i++)
{
x[i]=read();
}
bulid(rtt,1,n+1);
for(int i=1;i<=m;i++)
{
LL a,b,c,d;
a=read();
if(a==1)
{
b=read();c=read();d=read();
add(rtt,b,c+1,d);
}
if(a==2)
{
b=read();c=read();
cout<<getsum(rtt,b,c+1)<<endl;
}
}
}