P3373 【模板】線段樹 2

題目連接

P3373 【模板】線段樹 2ios

思路

這題乍一看以爲好難啊,而後咱們來仔細分析一下題目函數

題目說有兩種修改操做ui

1.區間加某一值
2.區間乘某一值spa

首先想到的思路必定是打兩個$lazymark$
在這兩個操做有前後,我$ri$,那麼咱們就應該來仔細看一下前後順序對程序的影響code

順序無非就是兩種:blog

1.先乘後加
先乘後加和數學同樣,因此咱們來先看一下這種
$tree[ls].date=(tree[ls].date\times tree[x].cheng % p+tree[x].jia\times (r-l+1) % p) % p $
如此看來咱們改變$cheng$的值時,只須要把$jia$去乘一下$cheng$就好了
這樣來看好像很對.........其實就是很對get

2.先加後乘
那麼咱們來看一下這個
$tree[ls].date=(tree[ls].date+ tree[x].jia)\cdot tree[root].cheng % p $
這樣子的化就無法向上面的代碼同樣更新$cheng$時去維護$jia$了數學

看完這裏就沒什麼難的了,就是要寫兩個$update$去分別維護$cheng,jia$兩個$lazymark$string

上面的代碼顯示不全,就放張圖吧

口胡

來詳細解釋(口胡)一波:
如下解釋不針對題目只是口胡一波

如今咱們要對區間$[l,r]$進行一坨的加和乘的操做

先把它當作加法優先的狀況

$(sum+lazy_{jia}) \times lazy_{cheng}$

很容易看出來
若是我更新了$ lazy_{cheng}$那麼$lazy_{jia}$也要改變因此咱們變形一下

$(sum \times lazy_{cheng})+lazy_{jia}*lazy_{cheng}$

設$sjpnb=lazy_{jia}*lazy_{cheng}$

那麼就變成了;

$(sum \times lazy_{cheng})+sjpnb$

如此來看$lazy_{cheng}$改變就不會致使$lazy_{jia}$變了
咱們把$sjpnb$當作$lazy_{jia}$不就ok了?

口胡完成有什麼錯誤請見諒,畢竟人家是菜雞嗎

代碼

代碼寫的可能複雜了些,$putdown$函數寫的有點複雜了,其實不必像我這樣寫

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<string>
#include<cstring>
#define int long long int
#define lowbit(x) x & -x
const int N=100000;
using namespace std;
inline int read() {
    char c = getchar();
    int x = 0, f = 1;
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int n,m,p,a[N*4];
struct node {
    int date;
    int cheng;
    int jia;
} tree[N*4+10];
void pushup(int root) {
    tree[root].date=(tree[root<<1].date+tree[root<<1|1].date)%p;
}
void build(int root,int l,int r) {
    tree[root].cheng=1;
    if(l==r) {
        tree[root].date=a[l];
        return ;
    }
    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) {
    int ls=x<<1,rs=x<<1|1,mid=(l+r)>>1;
    tree[ls].date=(tree[ls].date*tree[x].cheng%p+tree[x].jia*(mid-l+1)%p)%p;
    tree[ls].cheng=(tree[ls].cheng*tree[x].cheng)%p;
    tree[ls].jia=(tree[ls].jia*tree[x].cheng+tree[x].jia)%p;
    tree[rs].date=(tree[rs].date*tree[x].cheng%p+tree[x].jia*(r-(mid+1)+1)%p)%p;
    tree[rs].cheng=(tree[rs].cheng*tree[x].cheng)%p;
    tree[rs].jia=(tree[rs].jia*tree[x].cheng+tree[x].jia)%p;
    tree[x].jia=0;
    tree[x].cheng=1;
    return;
}
void update_cheng(int root,int l,int r,int x,int y,int k) {
    if(r<x || l>y) return ;
    if(l>=x & r<=y) {
        tree[root].date=(tree[root].date*k)%p;
        tree[root].cheng=(tree[root].cheng*k)%p;
        tree[root].jia=(tree[root].jia*k)%p;
        return;
    }
    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) {
    if(r<x || l>y) return ;
    if(l>=x & r<=y) {
        tree[root].date=(tree[root].date+k*(r-l+1)%p)%p;
        tree[root].jia=(tree[root].jia+k)%p;
        return;
    }
    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) {
    if(r<x || l>y) return 0;
    if(l>=x && r<=y) {
        return tree[root].date;
    }
    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() {
    scanf("%lld %lld %lld",&n,&m,&p);
    for(int i=1; i<=4*n; i++) tree[i].cheng=1;
    for(int i=1; i<=n; i++) {
        scanf("%lld",&a[i]);
    }
    build(1,1,n);
    int opt,x,y,k;
    while(m--) {
        scanf("%lld",&opt);
        if(opt==1) {
            scanf("%lld %lld %lld",&x,&y,&k);
            update_cheng(1,1,n,x,y,k);
        }
        if(opt==2) {
            scanf("%lld %lld %lld",&x,&y,&k);
            update_jia(1,1,n,x,y,k);
        }
        if(opt==3) {
            scanf("%lld %lld",&x,&y);
            cout<<query(1,1,n,x,y)%p<<endl;
        }
    }
    return 0;
}
相關文章
相關標籤/搜索