luogu3373 模板題 線段樹2(又加又乘)

2021-08-15 14:59:07 字數 1356 閱讀 8023

題目傳送門

題目大意:

1、題面是常規的線段樹:兩種區間修改(有加有乘)+區間求和;

解題思路:

1、單種的區間操作和區間求值都沒什麼問題,難就難在兩個lazy怎麼處理;

2、先乘還是先加,只要弄明白了,這題就切了:

3、情況1:當區間乘以 k 的時候:

1)當前是區間乘 k,點 x 的值,必然乘 k;√

2)x 的乘法lazy 也乘 k;√

3)x 的加法lazy 也乘 k!(難點1: x 管理的區間內,本來每個位置 應該加上(x的加法lazy),

現在整個區間都乘 k 了,將來要加那部分,自然也要乘 k~)

4、情況2:當區間加上 k 的時候:正常做就好了,不會干擾到乘法; √

5、情況3:下放 lazy 怎麼辦?

1)先下放乘法!記得兒子們的(加法lazy)也要乘喔;

2)後下放加法!

3)解釋:先放加法的話,後放的乘法會「乘多」了一部分;因為乘法已經乘進了(加法lazy),不會「乘少」。

上**(上面的註解看懂的了嗎?不用註解:再看;):

#include#define ll long long

const int mx=100005;

int n,m,lt=0;

ll p;

struct nodtt[mx*2];

void bt(int l,int r)

t[x].c=(t[ls].c+t[rs].c)%p;

}void cheng(int x,int l,int r,ll k)

int m=(t[x].l+t[x].r)/2,ls=t[x].ls,rs=t[x].rs;

upda(x,ls,rs);

if(r<=m) cheng(ls,l,r,k);

else if(l>m) cheng(rs,l,r,k);

else

t[x].c=(t[ls].c+t[rs].c)%p;

}ll fsum(int x,int l,int r)

int m=(t[x].l+t[x].r)/2,ls=t[x].ls,rs=t[x].rs;

upda(x,ls,rs);

if(r<=m) return fsum(ls,l,r);

else if(l>m) return fsum(rs,l,r);

else return (fsum(ls,l,m)+fsum(rs,m+1,r))%p;

}int main()

int a,x,y;

while(m--)

if(a==2)

if(a==3)

}return 0;

}

luogu3373 模板 線段樹 2

題面 已知乙個數列,你需要進行下面三種操作 1.將某區間每乙個數乘上x 2.將某區間每乙個數加上x 3.求出某區間每乙個數的和 題解區間修改 區間查詢。維護兩個lazytag include include using namespace std const int maxn 100010 type...

luogu 3373 模板 線段樹2

如題,已知乙個數列,你需要進行下面兩種操作 1.將某區間每乙個數加上x 2.將某區間每乙個數乘上x 3.求出某區間每乙個數的和 輸入格式 第一行包含三個整數n m p,分別表示該數列數字的個數 操作的總個數和模數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行每行包...

Luogu3373 模板 線段樹 2

不寫線段樹,就是要分塊!同樣需要打標記 在任何時候,a i mul times a i add bel i 表示 i 屬於哪一塊,a i 表示第 i 個位置的真實值 但是由於標記都是整塊整塊打上去的,無法單點修改,本來可能還可以利用逆元強行修改,問題是 p 571373 不是質數,那麼如何處理零散的...