使用懒惰的传播对于超过2种查询懒惰

2023-09-11 22:42:00 作者:我没你想的那么坚强

我有一个问题有很多的查询这是四种类型:

添加到范围。

初始化一个范围。

乘以一个范围标。

查找运行总和在一定范围内。

由于查询是在庞大的数字我都用段树懒传播,但我停留在如何使用延迟传播上超过200种的查询。 我将如何能够识别,当更新到稍后进行,那么什么类型的更新(即加法,乘法,初始化)将被做?

解决方案

1.2.3。这是简单的初始化和更新的部分。

 结构信息
{
    INT道具,总和;
}树[MX * 3]。

无效更新(INT节点,INT B,INT E,诠释我,诠释J,INT X)
{
    如果(I> e || J< b)退回;
    如果(B> = I和急症< = j)条
    {
        树[节点] .SUM + =((E-B + 1)* X);
        树[节点] .prop + = X;
        返回;
    }
    INT左=节点* 2;
    INT右=(节点* 2)1;
    诠释中期=(B + E)/ 2;
    更新(左,B,中,I,J,X);
    更新(右,中+ 1,E,I,J,X);
    树[节点] .SUM =树[左] .SUM +树[右] .SUM +(E-B + 1)*树[节点] .prop;

}
 

4,本是查询部分:

  INT查询(INT节点,INT B,INT E,诠释我,诠释J,INT随身= 0)
{
    如果(I> e || J< B)返回0;

    如果(B> = i和e控制= j)条回归树[节点] .SUM +携带*(E-B + 1);

    INT左=节点<&小于1;
    INT右=(节点<&小于1)1;
    INT中期=(B + E)>> 1;

    INT P1 =查询(左,B,中,I,J,携带+树[节点] .prop);
    INT P2 =查询(右,中+ 1,E,I,J,携带+树[节点] .prop);

    返回P1 + P2;
}
 

和从

 更新(1,1,number_of_element,first_range,last_range,价值);
查询(1,1,N,first_range,last_range);
 
优秀科普作品聚一聚,传播健康超有趣

  

下面,树是段树。每个节点包含两个   信息。一个是你前加入哪个号码有。道具意志   存储历史。和总和是节点的总价值。

**您的评论后:

  //初始化:

无效的init(INT节点,INT B,INT E)
{
    如果(二== E)
    {
        树[节点] = ARR [B]。
        返回;
    }
    INT左=节点* 2;
    INT右=节点* 2 + 1;
    诠释中期=(B + E)/ 2;
    的init(左,B,中);
    的init(右,中+ 1,E);
    树[节点] =树[左] +树[右]
}
 

I have a question with a lot of queries which are of four types:

Add to range.

Initialize a range.

Multiply a range with scalar.

Find running sum over a range.

Since queries are in huge numbers I have to use segment tree with lazy propagation but I am stuck on how to use lazy propagation on more than 2 types of queries. How would I be able to identify that when updates are to be made later, then what type of update(i.e. addition, multiplication, initializing) is to be made?

解决方案

1.2.3. This is the simple initialization and update part.

struct info
{
    int prop,sum;
} tree[mx*3];

void update(int node,int b,int e,int i,int j,int x)
{
    if (i > e || j < b) return;
    if (b >= i && e <= j)
    {
        tree[node].sum+=((e-b+1)*x);
        tree[node].prop+=x;
        return;
    }
    int Left=node*2;
    int Right=(node*2)+1;
    int mid=(b+e)/2;
    update(Left,b,mid,i,j,x);
    update(Right,mid+1,e,i,j,x);
    tree[node].sum=tree[Left].sum+tree[Right].sum+(e-b+1)*tree[node].prop;

}

4.This is the query part:

int query(int node,int b,int e,int i,int j,int carry=0)
{
    if (i > e || j < b) return 0;

    if(b>=i and e<=j) return tree[node].sum+carry*(e-b+1);

    int Left=node<<1;
    int Right=(node<<1)+1;
    int mid=(b+e)>>1;

    int p1 = query(Left, b,mid, i, j, carry+tree[node].prop); 
    int p2 = query(Right, mid+1, e, i, j,carry+tree[node].prop);

    return p1+p2;
}

And from main

update(1,1,number_of_element,first_range,last_range,value);
query(1,1,n,first_range,last_range);

Here, tree is the segment tree. Every node will contain two informations. One is with which number you added before. prop will store that history. And sum is the total value of that node.

**After your comment:

//Initialization:

void init(int node,int b,int e)
{
    if(b==e)
    {
        tree[node]=arr[b];
        return;
    }
    int Left=node*2;
    int Right=node*2+1;
    int mid=(b+e)/2;
    init(Left,b,mid);
    init(Right,mid+1,e);
    tree[node]=tree[Left]+tree[Right];
}