题目大意:维护一个序列,提供三种操作:
1.将区间中每一个点的权值乘上一个数
2.将区间中每一个点的权值加上一个数
3.求一段区间的和对p取模的值
2631的超^n级弱化版,写2631之前可以拿这个练练手。。。
线段树区间修改,让学校的大神指导了一下ZKW的区间修改方法,很好理解,但是代码还是快不了。。。回头再改改代码吧 可能是我写的太渣了
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 100100 using 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) ); } } }
BZOJ 1798 AHOI2009 Seq 维护序列 线段树
原文地址:http://blog.csdn.net/popoqqq/article/details/39639721