update1:加入树状数组维护,另外修复几个bug
bug:当修改的 A_x 在树的最后一层时,分段时会出现问题,因为树的最后一层不一定满。考虑建立虚点,将其补全成一棵满二叉树。
#include <bits/stdc++.h>
using namespace std;
struct node{
int lson,rson,fanum;
int pointnum[20][6];
};
struct ti{
int now,father,dept;
};
int a[100000];
node willam_tree[100000];
int lblock[1000],rblock[1000],tot=0,cnt=0;
int sum[100000],deep[100000],lg[100000],allsums[1000];
int fa[100000][30];
int n,q,numt=1,mxn2=1,cntn2=0,maxdeep=-1;
void build(int nw,int f,int dep){
queue <ti>q;
q.push((ti){nw,f,dep});
while(!q.empty()){
ti n6=q.front();
q.pop();
nw=n6.now;
f=n6.father;
dep=n6.dept;
if(nw>=n){
willam_tree[nw].fanum=0;
}else if(nw!=0){
willam_tree[nw].fanum=sum[nw]+(allsums[dep-1]-sum[f]);
}
willam_tree[nw].lson=++cnt;
willam_tree[nw].rson=++cnt;
if(willam_tree[nw].rson<mxn2){
q.push((ti){willam_tree[nw].lson,nw,dep+1});
q.push((ti){willam_tree[nw].rson,nw,dep+1});
}else if(willam_tree[nw].lson<mxn2){
q.push((ti){willam_tree[nw].lson,nw,dep+1});
}
}
}
void dfs(int now,int fth)
{
fa[now][0]=fth;
if(fth==-1){
deep[now]=0;
}else{
deep[now]=deep[fth]+1;
}
for(int i=1; i<=lg[deep[now]]; i++)
{
fa[now][i]=fa[fa[now][i-1]][i-1];
}
if(willam_tree[now].lson<mxn2){
dfs(willam_tree[now].lson,now);
}
if(willam_tree[now].rson<mxn2){
dfs(willam_tree[now].rson,now);
}
maxdeep=max(maxdeep,deep[now]+1);
}
int lglg[10]={1,2,4,8,16,32,64,128,256,512};
void add(int x,int y,int w){
y--;
for(int i=0;i<6;i++){
willam_tree[x].pointnum[y+1][i]+=w;
y/=2;
}
}
int de(int x,int l,int r){
int anss2=0;
for(int i=5;i>=0 && l<=r;i--){
if(l+lglg[i]<=r+1){
anss2+=willam_tree[x].pointnum[l][i];
l+=lglg[i];
}
}
return anss2;
}
int ask(int x,int firsts){
if(x==-1){
return -a[0];
}
int anss=de(x,1,firsts);
if(x==0){
return anss;
}
return ask(fa[x][0],firsts)+anss+willam_tree[x].fanum;
}
void update(int p,int zz){
int lx=p,rx=rblock[deep[p]+1],ly=lblock[deep[willam_tree[p-1].rson]+1]==0 ? mxn2/2-1 : lblock[deep[willam_tree[p-1].rson]+1],ry=min(n-1,willam_tree[p-1].rson);
if(deep[p]+1==deep[willam_tree[p-1].rson]+1){
add(0,deep[p]+1,zz);
return;
}
if(deep[p]+1==maxdeep){
ly=ry+1;
}
if(rblock[deep[p]+1]==n-1){
rx=mxn2-1;
}
for(int z=mxn2,r=cntn2;z>=1 && lx<=rx;z/=2,r--){
if(rx-z>=lx-1){
if(rx>=n && rx-z+1>=n){
continue;
}
if(r==0){
add(rx-z+1,deep[p]+1,zz);
}else{
add(fa[rx-z+1][r-1],deep[p]+1,zz);
}
rx-=z;
}
}
for(int z=mxn2,r=cntn2;z>=1 && ly<=ry;z/=2,r--){
if(ly+z<=ry+1){
if(r==0){
add(ly,deep[willam_tree[p-1].rson]+1,zz);
}else{
add(fa[ly][r-1],deep[willam_tree[p-1].rson]+1,zz);
}
ly+=z;
}
}
}
int main(){
lblock[0]=0;
cin >> n >> q;
while(mxn2<n){
mxn2*=2;
cntn2++;
}
for(int i=0;i<n;i++){
cin >> a[i];
if(numt==i+1){
rblock[tot]=i-1;
lblock[++tot]=i;
numt*=2;
}
if(i==n-1){
rblock[tot]=i;
}
}
sum[1]=a[0];
for(int i=2;i<=tot;i++){
sum[lblock[i]]=a[lblock[i]];
for(int j=lblock[i]+1;j<=rblock[i];j++){
sum[j]=a[j]+sum[j-1];
if(j==rblock[i]){
allsums[i]=sum[j];
}
}
}
build(0,-1,1);
for(int i=1; i<=mxn2; i++)
{
lg[i]=lg[i-1]+(1<<lg[i-1]==i);
}
dfs(0,-1);
while(q--){
int opt,x,y;
cin >> opt >> x >> y;
if(opt==1){
x--;
update(x,y);
}else{
x--;
y--;
int deptx=deep[x-1]+1;
int depty=deep[y]+1;
cout << (ask(y,depty)+a[0])-(ask(x-1,deptx)+a[0]) << endl;
}
}
return 0;
}