zhw大神线段树姿势

for (i=131072; i<262144; i++)
  tree[i][0]=tree[i][1]=i;
for (i=131071; i>=1; i--)
  tree[i][0]=tree[i+i][0],
  tree[i][1]=tree[i+i+1][1];
void Down(int x)
{
    tree[x+x][2]+=tree[x][2];
    tree[x+x+1][2]+=tree[x][2];
    tree[x+x][3]+=tree[x][2]*
        (tree[x+x][1]-tree[x+x][0]+1);
    tree[x+x+1][3]+=tree[x][2]*
        (tree[x+x+1][1]-tree[x+x+1][0]+1);
    tree[x][2]=0;
}
int work(int root,int l,int r,int k)
{
    if (tree[root][0]==l &&
        tree[root][1]==r)
        {
            tree[root][2]+=k;
            tree[root][3]+=k*(r-l+1);
            return 0;
        }
    tree[root][3]+=k*(r-l+1);
    //Down(root);
    int mid=(tree[root][0]+tree[root][1])/2;
    if (l<=mid)
        work(root+root,l,min(mid,r),k);
    if (r>mid)
        work(root+root+1,max(mid+1,l),r,k);
  //  tree[root][3]=tree[root+root][3]+tree[root+root+1][3];
    return;
}
int work2(int root,int l,int r)
{
    if (tree[root][0]==l &&
        tree[root][1]==r)
        return tree[root][3];
    Down(root);
    int mid=(tree[root][0]+tree[root][1])/2;
    int p=0,q=0;
    if (l<=mid)
        p=work2(root+root,l,min(mid,r));
    if (r>mid)
        q=work2(root+root+1,max(mid+1,l),r);
    return p+q;
}

while (Q--)
{
    cin>>A;
    if (A==1)
    {
        cin>>x>>y>>z;
        work(1,x+131071,y+131071,z);
    }
    if (A==2)
    {
        cin>>x>>y;
        cout<<work2(1,x+131071,y+131071);
    }
}
tree[i][0] 表示编号最小的叶子
tree[i][1] 编号最大的叶子
tree[i][2] 以i为根,所有叶子一次性全部加的,
           总共加了多少。
tree[i][3] 以i为根,所有叶子的权值之和是多少

 

posted @ 2017-05-01 19:41  安月冷  阅读(250)  评论(0编辑  收藏  举报