UESTC

来源:互联网 发布:海康威视报警键盘编程 编辑:程序博客网 时间:2024/06/16 10:49

题意: 给一个数组, 有三个操作
1. 区间乘法
2. 区间加法
3. 询问区间的和并取模。

思路:两个数组作为懒惰标记。分别是对加法和乘法的对子树传递的保存。每次乘法时, 都要把sum数组也乘起来,在向下传递时就可以先乘法再加法,注意记录下一子树sum和mul的数值的更新。

#include <bits/stdc++.h>#define lk k<<1#define rk k<<1|1using namespace std;const int MAXN = 100005;const int mod = 1e9+7;typedef long long LL;struct T{    int l, r;    LL c;} tree[MAXN<<2];LL add[MAXN<<2], mul[MAXN<<2];void pushdown(int k, int d,int p){    if(mul[k]==1&&add[k]==0)        return ;    tree[k<<1].c=tree[k<<1].c*mul[k]%p;    tree[k<<1|1].c=tree[k<<1|1].c*mul[k]%p;    tree[k<<1].c=(tree[k<<1].c+add[k]*(d-(d>>1)))%p;    tree[k<<1|1].c=(tree[k<<1|1].c+add[k]*(d>>1))%p;    mul[k<<1]=mul[k]*mul[k<<1]%p;    mul[k<<1|1]=mul[k]*mul[k<<1|1]%p;    add[k<<1]=(add[k<<1]*mul[k]+add[k])%p;    add[k<<1|1]=(add[k]+add[k<<1|1]*mul[k])%p;    add[k]=0;    mul[k]=1;    return ;}void pushup(int k,int p){    tree[k].c=(tree[k<<1].c+tree[k<<1|1].c)%p;}void build(int l, int r, int k, int p){    tree[k].l=l;    tree[k].r=r;    tree[k].c=0;    mul[k]=1;    add[k]=0;    if(l==r)    {        scanf("%lld", &tree[k].c);        return;    }    int mid=(tree[k].l+tree[k].r)>>1;    build(l, mid, k<<1, p);    build(mid+1,r,k<<1|1, p);    pushup(k, p);}void update(int l, int r, int k, LL c, int op, int p){    if(tree[k].l>=l&&tree[k].r<=r){        if(op==1){            add[k]=add[k]*c%p;            mul[k]=mul[k]*c%p;            tree[k].c=tree[k].c*c%p;        }        else{            add[k]=(add[k]+c)%p;            tree[k].c=(tree[k].c+(tree[k].r-tree[k].l+1)*c)%p;        }        return;    }    pushdown(k, tree[k].r-tree[k].l+1, p);    int mid=(tree[k].l+tree[k].r)>>1;    if(l<=mid)        update(l,r,k<<1,c,op,p);    if(r>mid)        update(l,r,k<<1|1,c,op,p);    pushup(k,p);}LL query(int l, int r, int k, int p){    if(tree[k].l>=l&&tree[k].r<=r)        return tree[k].c%p;    pushdown(k, tree[k].r-tree[k].l+1, p);    LL ans=0;    int mid = (tree[k].l+tree[k].r)>>1;    if(l<=mid)        ans=(ans+query(l,r,k<<1,p))%p;    if(r>mid)        ans=(ans+query(l,r,k<<1|1, p))%p;    //pushup(k, p);    return ans%p;}int main(){    int n, m, p;    while(~scanf("%d %d", &n,&p))    {        build(1, n, 1, p);        scanf("%d", &m);        while(m--)        {            int op,l,r;            LL v;            scanf("%d %d %d", &op, &l, &r);            if(op==1||op==2)            {                scanf("%lld", &v);                update(l, r, 1, v, op, p);            }            else            {                printf("%lld\n", query(l, r, 1, p));            }        }    }    return 0;}
原创粉丝点击