数列求和【線分樹基礎】
1909 ワード
線分樹の基礎問題
操作は含まれています.1.ポイント修正2.区間修正3.区間照会
操作は含まれています.1.ポイント修正2.区間修正3.区間照会
// :
#include
#define maxn 10007//
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
int sum[maxn<<2],add[maxn<<2];//sum ,add
int a[maxn],n;// 1
//PushUp , 。
void PushUp(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
//Build
void Build(int l,int r,int rt)
{
if(l==r){
sum[rt]=a[l];
return;
}
int m=(l+r)>>1;
//
Build(ls);
Build(rs);
//
PushUp(rt);
}
// , A[L]+=c
void Update1(int L,int c,int l,int r,int rt)
{
if(l==r){// ,
sum[rt]+=c;
return;
}
int m=(l+r)>>1;
//
if(L<=m)
Update1(L,c,ls);
else
Update1(L,c,rs);
PushUp(rt);// ,
}
//
void PushDown(int rt,int ln,int rn)
{
//ln,rn
if(add[rt]){
//
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
// sum add
sum[rt<<1]+=add[rt]*ln;
sum[rt<<1|1]+=add[rt]*rn;
//
add[rt]=0;
}
}
//
void Update2(int L,int R,int C,int l,int r,int rt)
{
if(L<=l&&r<=R){// [L,R]
sum[rt]+=C*(r-l+1);// ,
add[rt]+=C;// add , sum
return;
}
int m=(l+r)>>1;
PushDown(rt,m-l+1,r-m);//
// [L,R] ,
if(L<=m)
Update2(L,R,C,ls);
if(R>m)
Update2(L,R,C,rs);
PushUp(rt);//
}
//
int Query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)// ,
return sum[rt];
int m=(l+r)>>1;
// , sum
PushDown(rt,m-l+1,r-m);
//
int ans=0;
if(L<=m)
ans+=Query(L,R,ls);
if(R>m)
ans+=Query(L,R,rs);
return ans;
}
int main()
{
n=100;
for(int i=1;i<=n;i++)
a[i]=i;
//
Build(1,n,1);
int ans=Query(1,100,1,n,1);
printf("%d
",ans);
return 0;
}