BZOJ 1798 AHOI2009 Seq 维护序列 线段树

来源:互联网 发布:怎样看网络直播送礼物 编辑:程序博客网 时间:2024/05/17 05:56

题目大意:维护一个序列,提供三种操作:

1.将区间中每一个点的权值乘上一个数

2.将区间中每一个点的权值加上一个数

3.求一段区间的和对p取模的值

2631的超^n级弱化版,写2631之前可以拿这个练练手。。。

线段树区间修改,让学校的大神指导了一下ZKW的区间修改方法,很好理解,但是代码还是快不了。。。回头再改改代码吧 可能是我写的太渣了

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define M 100100using namespace std;typedef long long ll;struct abcd{    ll sum,siz,add_mark,times_mark;    void add(ll x);    void times(ll x);}tree[263000];int m,n,p,q;void abcd :: add(ll x){    sum+=x*siz;    sum%=p;    add_mark+=x;    add_mark%=p;}void abcd :: times(ll x){    sum*=x;    sum%=p;    add_mark*=x;    add_mark%=p;    times_mark*=x;    times_mark%=p;}void Build_Tree(){    int i;    for(i=q+1;i<=q+n;i++)    {        scanf("%d",&tree[i].sum);        tree[i].siz=1;        tree[i].add_mark=0;        tree[i].times_mark=1;    }    for(i=q-1;i;i--)    {        tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;        tree[i].sum%=p;        tree[i].siz=tree[i<<1].siz+tree[i<<1|1].siz;        tree[i].add_mark=0;        tree[i].times_mark=1;    }}int stack[M],top;void Push_Down(int x){    if(x>=q)        return ;    if(tree[x].times_mark^1)    {        tree[x<<1  ].times(tree[x].times_mark);        tree[x<<1|1].times(tree[x].times_mark);        tree[x].times_mark=1;    }    if(tree[x].add_mark)    {        tree[x<<1  ].add(tree[x].add_mark);        tree[x<<1|1].add(tree[x].add_mark);        tree[x].add_mark=0;    }}void Push_Down(int x,int y){    for(x+=q-1,y+=q+1;x^y;x>>=1,y>>=1)        stack[++top]=x,stack[++top]=y;    for(;x;x>>=1)        stack[++top]=x;    while(top)        Push_Down(stack[top--]);}void Add(int x,int y,ll z){    for(x+=q-1,y+=q+1;x^y^1;x>>=1,y>>=1)    {        if(~x&1)tree[x^1].add(z);        if( y&1)tree[y^1].add(z);    }}void Times(int x,int y,ll z){    for(x+=q-1,y+=q+1;x^y^1;x>>=1,y>>=1)    {        if(~x&1)tree[x^1].times(z);        if( y&1)tree[y^1].times(z);    }}void Push_Up(int x){    if(x>=q)        return ;    tree[x].sum=tree[x<<1].sum+tree[x<<1|1].sum;    tree[x].sum%=p;}void Push_Up(int x,int y){    for(x+=q-1,y+=q+1;x^y;x>>=1,y>>=1)        Push_Up(x),Push_Up(y);    for(;x;x>>=1)        Push_Up(x);}ll Get_Ans(int x,int y){    int re=0;    for(x+=q-1,y+=q+1;x^y^1;x>>=1,y>>=1)    {        if(~x&1)re+=tree[x^1].sum,re%=p;        if( y&1)re+=tree[y^1].sum,re%=p;    }    return re;}int main(){    int i,x,y,c;    ll z;    cin>>n>>p;    for(q=1;q<=n+1;q<<=1);    Build_Tree();    cin>>m;    for(i=1;i<=m;i++)    {        scanf("%d",&c);        if(c==1)        {            scanf("%d%d%lld",&x,&y,&z);            Push_Down(x,y);            Times(x,y,z);            Push_Up(x,y);        }        else if(c==2)        {            scanf("%d%d%lld",&x,&y,&z);            Push_Down(x,y);            Add(x,y,z);            Push_Up(x,y);        }        else        {            scanf("%d%d",&x,&y);            Push_Down(x,y);            printf("%lld\n", Get_Ans(x,y) );        }    }}


0 0