1009 [AHOI2009]SEQ 维护序列SEQ 区间加 区间乘

//-------------------------代码----------------------------

#define int ll
const int N = 1e5+10;
int n,m,p;
int a[N];
struct node{
    int l,r,s,la1,la2;
} tr[N<<2];

void push_up(int u) {
    tr[u].s = (tr[ul].s + tr[ur].s)% p;
}

void push_down(int u) {
    if(tr[u].l==tr[u].r)return ;
    if(tr[u].la1==0&&tr[u].la2==1)return ;
    int x=tr[u].la1;tr[u].la1=0;
    int y=tr[u].la2;tr[u].la2=1;
    //更新子节点
    tr[ul].la1=(tr[ul].la1*y)%p;tr[ul].la2=(tr[ul].la2*y)%p;
    tr[ul].s=(tr[ul].s*y)%p;
    tr[ul].la1=(tr[ul].la1+x)%p;tr[ul].s=(tr[ul].s+tr_len(ul)*x)%p;
     
    tr[ur].la1=(tr[ur].la1*y)%p;tr[ur].la2=(tr[ur].la2*y)%p;
    tr[ur].s=(tr[ur].s*y)%p;
    tr[ur].la1=(tr[ur].la1+x)%p;tr[ur].s=(tr[ur].s+tr_len(ur)*x)%p;
}

void build(int u,int l,int r) {
    if(l == r) {
        tr[u] = {l,r,a[l]%p,0,1};
        rt;
    }
    int mid = l + r >> 1;
    build(u<<1,l,mid);build(u<<1|1,mid+1,r);
    tr[u] = {l,r,0,0,1};
    push_up(u);
}

int query(int u,int l,int r) {
    if(l <= tr[u].l && tr[u].r <= r) return tr[u].s;
    if(l > tr[u].r || r < tr[u].l) return 0;
    push_down(u);
    return (query(ul,l,r) + query(ur,l,r)) % p;
}

void modify1(int u,int l,int r,int c) {
    if(l <= tr[u].l && tr[u].r <= r) {
        tr[u].la1=(tr[u].la1+c)%p;
        tr[u].s=(tr[u].s+tr_len(u)*c)%p;
        rt;
    }
    push_down(u);
    int mid = tr[u].l + tr[u].r >> 1;
    if(l <= mid) modify1(u<<1,l,r,c);
    if(mid < r ) modify1(ur,l,r,c);
    push_up(u);
}

void modify2(int u,int l,int r,int c) {
    if(l <= tr[u].l && tr[u].r <= r) {
        tr[u].s = tr[u].s * c % p;
        tr[u].la2 *= c;tr[u].la1 *= c;
        tr[u].la2 %= p;tr[u].la1 %= p;
        rt;
    }
    push_down(u);
    int mid = tr[u].l + tr[u].r >> 1;
    if(l <= mid) modify2(u<<1,l,r,c);
    if(mid < r ) modify2(ur,l,r,c);
    push_up(u);
}


void solve()
{
//    cin>>n>>m;
    cin>>n>>p;
    fo(i,1,n) cin>>a[i];
    cin>>m;
    build(1,1,N-3);
    while(m -- ) {
        int op,t,g,c;
        cin>>op>>t>>g;
        if(op == 2) {
            cin>>c;
            modify1(1,t,g,c);
        } else if(op == 1) {
            cin>>c;
            modify2(1,t,g,c);
        } else if(op == 3) {
            cout<<query(1,t,g)% p <<endl;
        }
    }
}
void main_init() {}
signed main(){
    AC();clapping();TLE;
    cout<<fixed<<setprecision(12);
    main_init();
//  while(cin>>n,n)
//  while(cin>>n>>m,n,m)
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

链接:https://ac.nowcoder.com/acm/contest/26896/1009
来源:牛客网

题目描述

老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。 有长为N的数列,不妨设为a1,a2,…,aN
有如下三种操作形式: 
(1)把数列中的一段数全部乘一个值; 
(2)把数列中的一段数全部加一个值; 
(3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。

输入描述:

第一行两个整数N和P(1 ≤ P ≤ 1000000000)。
第二行含有N个非负整数,从左到右依次为a1,a2,…,aN, (0 ≤ ai ≤ 1000000000,1 ≤ i ≤ N)。
第三行有一个整数M,表示操作总数。
从第四行开始每行描述一个操作,输入的操作有以下三种形式: 
操作1:“1 t g c”(不含双引号)。表示把所有满足t ≤ i ≤ g的ai改为ai×c (1 ≤ t ≤ g ≤ N,0 ≤ c ≤ 1000000000)。
操作2:“2 t g c”(不含双引号)。表示把所有满足t ≤ i ≤ g的ai改为ai+c (1 ≤ t ≤ g ≤ N,0 ≤ c ≤ 1000000000)。 
操作3:“3 t g”(不含双引号)。询问所有满足t ≤ i ≤ g的ai的和模P的值 (1 ≤ t ≤ g ≤ N)。 
同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

输出描述:

对每个操作3,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。
示例1

输入

复制
7 43
1 2 3 4 5 6 7
5
1 2 5 5
3 2 4
2 3 7 9
3 1 3
3 4 7

输出

复制
2
35
8

备注:

对于全部的测试点,保证 0≤p,ai,c≤109,1≤t≤g≤n。0 \leq p, a_i, c \leq 10^9 ,1 \leq t \leq g \leq n。0p,ai,c1091tgn
posted @ 2022-08-09 15:20  er007  阅读(26)  评论(0)    收藏  举报