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为根,所有叶子的权值之和是多少

 

转载于:https://www.cnblogs.com/L-Memory/p/6792557.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值