您的位置:首页 > 运维架构

bzoj 1798 [Ahoi2009]Seq 维护序列seq(线段树+传标)

2016-03-29 19:26 525 查看
【题目链接】

  http://www.lydsy.com/JudgeOnline/problem.php?id=1798

【题意】

给定一个序列,要求提供区间乘/加,以及区间求和的操作

【思路】

线段树+传标。

下传标记的方式可以类比这里 click here

【代码】

#include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std;

typedef long long ll;
const int N = 2e5+10;

ll read() {
char c=getchar();
ll f=1,x=0;
while(!isdigit(c)) {
if(c=='-') f=-1; c=getchar();
}
while(isdigit(c))
x=x*10+c-'0',c=getchar();
return x*f;
}

int MOD ;

struct Tnode {
int u,l,r;
ll sum,add,mul;
void mulv(ll x) ;
void addv(ll x) ;
void pushdown() ;
void maintain() ;
} T[N<<2] ;
void Tnode::mulv(ll x) {
mul=(mul*x)%MOD;
sum=(sum*x)%MOD;
add=(add*x)%MOD;
}
void Tnode::addv(ll x) {
sum=(sum+(r-l+1)*x)%MOD;
add=(add+x)%MOD;
}
void Tnode::pushdown() {
if(mul!=1) {
T[u<<1].mulv(mul);
T[u<<1|1].mulv(mul);
mul=1;
}
if(add) {
T[u<<1].addv(add);
T[u<<1|1].addv(add);
add=0;
}
}
void Tnode::maintain() {
sum=(T[u<<1].sum+T[u<<1|1].sum)%MOD;
}
void update(int u,int L,int R,int x,int flag) {
T[u].pushdown();
if(L<=T[u].l&&T[u].r<=R) {
if(flag==0) T[u].addv(x);
else T[u].mulv(x);
} else {
int mid=T[u].l+T[u].r>>1;
if(L<=mid) update(u<<1,L,R,x,flag);
if(mid<R)  update(u<<1|1,L,R,x,flag);
T[u].maintain();
}
}
ll query(int u,int L,int R) {
T[u].pushdown();
if(L<=T[u].l&&T[u].r<=R)
return T[u].sum;
else {
int mid=T[u].l+T[u].r>>1;
ll ans=0;
if(L<=mid) ans=(ans+query(u<<1,L,R))%MOD;
if(mid<R)  ans=(ans+query(u<<1|1,L,R))%MOD;
return ans;
}
}

int n,m; ll a
;

void build(int u,int l,int r) {
T[u]=(Tnode){u,l,r,0,0,1};
if(l==r) {
T[u].sum=a[l]%MOD;
return ;
} else {
int mid=l+r>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
T[u].maintain();
}
}
/* Debug
int print(int u) {
T[u].pushdown();
if(T[u].l==T[u].r) printf("%d,%d\n",T[u].l,T[u].v);
else {
print(u<<1),print(u<<1|1);
}
}
*/
int main()
{
//    freopen("in.in","r",stdin);
//    freopen("out.out","w",stdout);
n=read(),MOD=read();
FOR(i,1,n) a[i]=read();
build(1,1,n);
m=read();
int op,l,r,x;
FOR(i,1,m) {
op=read(),l=read(),r=read();
if(op==1) {
x=read();
update(1,l,r,x,1);
} else
if(op==2) {
x=read();
update(1,l,r,x,0);
} else {
printf("%lld\n",query(1,l,r));
}
}
return 0;
}


P.S.我竟然蛋疼的存了一个v,还一本正经地累计到sum里 <_<
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: