目錄p3373 【模板】線段樹 2
這題乍一看覺得好難啊,然後我們來仔細分析一下題目
題目說有兩種修改操作
1.區間加某一值首先想到的思路一定是打兩個\(lazymark\)2.區間乘某一值
男就男在這兩個操作有先後,我\(ri\),那麼我們就應該來仔細看一下先後順序對程式的影響
順序無非就是兩種:
1.先乘後加
先乘後加和數學一樣,所以我們來先看一下這種
$tree[ls].date=(tree[ls].date\times tree[x].cheng\ %\ p+tree[x].jia\times (r-l+1)\ %\ p)\ %\ p \(
如此看來我們改變\)cheng\(的值時,只需要把\)jia\(去乘一下\)cheng$就行了
這樣來看好像很對.........其實就是很對
2.先加後乘
那麼我們來看一下這個
$tree[ls].date=(tree[ls].date+ tree[x].jia)\cdot tree[root].cheng\ %\ p \(
這樣子的化就沒法向上面的**一樣更新\)cheng\(時去維護\)jia$了
看完這裡就沒什麼難的了,就是要寫兩個\(update\)去分別維護\(cheng,jia\)兩個\(lazymark\)
上面的**顯示不全,就放張圖吧
來詳細解釋(口胡)一波:
以下解釋不針對題目只是口胡一波
現在我們要對區間\([l,r]\)進行一坨的加和乘的操作
先把它看成加法優先的情況
\((sum+lazy_) \times lazy_\)
很容易看出來
如果我更新了$ lazy_\(那麼\)lazy_$也要改變所以我們變形一下
\((sum \times lazy_)+lazy_*lazy_\)
設\(sjpnb=lazy_*lazy_\)
那麼就變成了;
\((sum \times lazy_)+sjpnb\)
如此來看\(lazy_\)改變就不會導致\(lazy_\)變了
我們把\(sjpnb\)看成\(lazy_\)不就ok了?
口胡完成有什麼錯誤請見諒,畢竟人家是菜雞嗎
**寫的可能複雜了些,\(putdown\)函式寫的有點複雜了,其實沒必要像我這樣寫
#include#include#include#include#include#include#include#include#include#include#define int long long int
#define lowbit(x) x & -x
const int n=100000;
using namespace std;
inline int read()
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}int n,m,p,a[n*4];
struct node tree[n*4+10];
void pushup(int root)
void build(int root,int l,int r)
int mid=(l+r)/2;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
pushup(root);
}void pushdown(int x,int l,int r)
void update_cheng(int root,int l,int r,int x,int y,int k)
pushdown(root,l,r);
int mid=(l+r)>>1;
update_cheng(root<<1,l,mid,x,y,k);
update_cheng(root<<1|1,mid+1,r,x,y,k);
pushup(root);
}void update_jia(int root,int l,int r,int x,int y,int k)
pushdown(root,l,r);
int mid=(l+r)>>1;
update_jia(root<<1,l,mid,x,y,k);
update_jia(root<<1|1,mid+1,r,x,y,k);
pushup(root);
}int query(int root,int l,int r,int x,int y)
pushdown(root,l,r);
int mid=(l+r)>>1;
return (query(root<<1,l,mid,x,y)+query(root<<1|1,mid+1,r,x,y))%p;
}signed main()
build(1,1,n);
int opt,x,y,k;
while(m--)
if(opt==2)
if(opt==3)
} return 0;
}
P3373 模板 線段樹2
如題,已知乙個數列,你需要進行下面三種操作 1.將某區間每乙個數乘上x 2.將某區間每乙個數加上x 3.求出某區間每乙個數的和 include include using namespace std const int maxn 100005 int n,m,p long long arr maxn...
P3373 模板 線段樹 2
ac 這裡的延遲標記要開兩個,分別記錄加法的值和乘法的值,但是乘法和加法的優先順序不一樣,不規定他們的順序的話會有錯誤,所以可以規定乘法優先,即規定好該結點的值等於該節點的值 父節點的乘法延遲標記的值 父節點加法延遲標記的值 區間長度,即,sum num 2 sum num 2 add num wc...
P3373 模板 線段樹 2
題目描述 如題,已知乙個數列,你需要進行下面三種操作 1.將某區間每乙個數乘上x 2.將某區間每乙個數加上x 3.求出某區間每乙個數的和 輸入格式 第一行包含三個整數n m p,分別表示該數列數字的個數 操作的總個數和模數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來...