P3373 模板 線段樹 2

2022-04-02 15:53:27 字數 2714 閱讀 7938

目錄p3373 【模板】線段樹 2

這題乍一看覺得好難啊,然後我們來仔細分析一下題目

題目說有兩種修改操作

1.區間加某一值

2.區間乘某一值

首先想到的思路一定是打兩個\(lazymark\)

在這兩個操作有先後,我\(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項的初始值。接下來...