1. 程式人生 > >線段樹的單點修改加區間修改

線段樹的單點修改加區間修改

const int maxn=1e6+5;
int a[maxn];    //存每個數的值
struct node
{
    int sum;
    int ll,rr;
}tree[maxn*4];

void Pushup(int id)       //區間合併
{
    tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
}

void Pushdown()     //區間下放,進行區間修改的時候用到
{

}

void Build(int id,int ll,int rr)        //建樹
{
    tree[id].ll=ll;
    tree[id].rr=rr;
    if(ll==rr)
    {
        tree[id].sum=a[ll];
        return;
    }
    int mid=(ll+rr)/2;
    //mid=ll+rr>>1;
    Build(id*2,ll,mid);
    Build(id*2+1,mid+1,rr);
    //Build(id<<1,ll,mid);
    //Build(id<<1|1,mid+1,rr);
    Pushup(id);
}

void Update(int id,int x,int y)       //修改
{
    if(tree[id].ll==tree[id].rr)
    {
        tree[id].sum=y;
        return;
    }
    int mid=(tree[id].ll+tree[id].rr)/2;
    if(x<=mid)
        Update(id*2,x,y);
    else
        Update(id*2+1,x,y);
    Pushup(id);
}

int Query(int id,int x,int y)        //查詢
{
    if(x<=tree[id].ll&&tree[id].rr<=y)//到頭的情況
        return tree[id].sum;
    int mid=(tree[id].ll+tree[id].rr)/2;
    if(y<=mid)                  //只需要訪問左邊
        return Query(id*2,x,y);
    else if(x>=mid+1)
        return Query(id*2+1,x,y);
    else
        return Query(id*2,x,y)+Query(id*2+1,x,y);
}
const int maxn=1e6+5;
long long int a[maxn];
long long int lazy[maxn*4];    //存每個數的值
struct node
{
	long long int sum;
	long long int ll,rr;
}tree[maxn*4];
void Pushup(int id)       //區間合併
{
    tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
}
void Pushdown(int id)     //區間下放,進行區間修改的時候用到
{
    if(lazy[id])
    {
        tree[id*2].sum+=lazy[id]*(tree[id*2].rr-tree[id*2].ll+1);
        tree[id*2+1].sum+=lazy[id]*(tree[id*2+1].rr-tree[id*2+1].ll+1);
        lazy[id*2]+=lazy[id];
        lazy[id*2+1]+=lazy[id];
        lazy[id]=0;
    }
}
void Build(int id,int ll,int rr)        //建樹
{
    lazy[id]=0;
    tree[id].ll=ll;
    tree[id].rr=rr;
    if(ll==rr)
    {
        tree[id].sum=a[ll];
        return;
    }
    int mid=(ll+rr)/2;
    //mid=ll+rr>>1;
    //Build(ltree);
    //Build(rtree);
    Build(id<<1,ll,mid);
    Build(id<<1|1,mid+1,rr);
    Pushup(id);
}
void Update(int id,int x,int y,int z)       //修改
{
    if(x<=tree[id].ll&&tree[id].rr<=y)
    {
        tree[id].sum+=z*(tree[id].rr-tree[id].ll+1);
        lazy[id]+=z;
        return;
    }
    int mid=(tree[id].ll+tree[id].rr)/2;
    Pushdown(id);
    if(y<=mid)
        Update(id*2,x,y,z);
    else if(x>=mid+1)
        Update(id*2+1,x,y,z);
    else
    {
        Update(id*2,x,y,z);
        Update(id*2+1,x,y,z);
    }
    Pushup(id);
}
long long int Query(int id,int x,int y)        //查詢
{
    if(x<=tree[id].ll&&tree[id].rr<=y)//到頭的情況
        return tree[id].sum;
    int mid=(tree[id].ll+tree[id].rr)/2;
    Pushdown(id);
    if(y<=mid)                  //只需要訪問左邊
        return Query(id*2,x,y);
    else if(x>=mid+1)
        return Query(id*2+1,x,y);
    else
        return Query(id*2,x,y)+Query(id*2+1,x,y);
}