題目傳送門
題目大意:
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 不是質數,那麼如何處理零散的...