NOIP 資訊學 奧賽 考綱 考點 模板 裸題 水題
阿新 • • 發佈:2019-01-04
//調了會,樣例通過,提交AC 2018-5-8 收穫是 對 線段樹 理解更深刻了
#include <stdio.h>
#include <string.h>
#define maxn 100100
#define LL long long
LL n,m,lazy[4*maxn],ans,max_k=-999999999;
struct node{
LL left,right,v;
}q[4*maxn];
void build(LL k,LL left,LL right){
LL mid=(left+right)/2;
q[k].left=left,q[k].right=right;
if(q[k].left==q[k].right){
scanf("%lld",&q[k].v);
if(max_k<k)max_k=k;//判斷最大節點位置
return ;
}
build(2*k,left,mid);
build(2*k+1,mid+1,right);
q[k].v=q[2*k].v+q[2*k+1].v;
}
void down(LL k){
LL v=lazy[k];
//此處多寫了此句q[k].v+=(q[k].right-q[k].left+1)*v;
if(2*k<=max_k){//判斷有無越界
lazy[2*k]+=v;
q[2*k].v+=(q[2*k].right-q[2*k].left+1)*v;//漏了此句
}
if(2*k+1<=max_k){//判斷有無越界
lazy[2*k+1]+=v;
q[2*k+1].v+=(q[2*k+1].right-q[2*k+1].left+1)*v;//漏了此句
}
lazy[k]=0;
}
void query(LL k,LL left,LL right){
LL mid=(q[k].left+q[k].right)/2;//此處寫成 LL mid=(left+right)/2;
if(left<=q[k].left&&q[k].right<=right){
ans+=q[k].v;
return ;
}
if(lazy[k])down(k);
if(left<=mid)query(2*k,left,right);
if(right>=mid+1)query(2*k+1,left,right);
}
void add(LL k,LL left,LL right,LL v){
LL mid=(q[k].left+q[k].right)/2;//此處寫成 LL mid=(left+right)/2;
if(left<=q[k].left&&q[k].right<=right){
q[k].v+=(q[k].right-q[k].left+1)*v;
lazy[k]+=v;//漏了此句
return ;
}
if(lazy[k])down(k);
if(left<=mid)add(2*k,left,right,v);//此處寫成 query(2*k,left,right)昏招
if(right>=mid+1)add(2*k+1,left,right,v);//此處寫成 query(2*k+1,left,right)昏招
q[k].v=q[2*k].v+q[2*k+1].v;
}
int main(){
LL i,cmd,x,y,v;
scanf("%lld%lld",&n,&m);
build(1,1,n);
memset(lazy,0,sizeof(lazy));
while(m--){
scanf("%lld",&cmd);
if(cmd==2){
ans=0;
scanf("%lld%lld",&x,&y);
query(1,x,y);
printf("%lld\n",ans);
}else{//cmd==1
scanf("%lld%lld%lld",&x,&y,&v);
add(1,x,y,v);
}
}
return 0;
}
//P3372 【模板】線段樹 1
//列舉的方式,猜測70分。
//果然,提交70分,測試點8,9,10 TLE 2018-5-7 18:01
#include <stdio.h>
#define maxn 100100
#define LL long long
LL a[maxn];
int main(){
LL n,m,i,j,cmd,x,y,k,sum;
scanf("%lld%lld",&n,&m);
for(i=1;i<=n;i++)scanf("%lld",&a[i]);
while(m--){
scanf("%lld",&cmd);
if(cmd==1){
scanf("%lld%lld%lld",&x,&y,&k);
for(i=x;i<=y;i++)a[i]+=k;
}else{
sum=0;
scanf("%lld%lld",&x,&y);
for(i=x;i<=y;i++)sum+=a[i];
printf("%lld\n",sum);
}
}
return 0;
}