bzoj1798: [Ahoi2009]Seq 维护序列seq 线段树
老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。 有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。
题解:维护两种lazy标记即可由于比+优限级高,所以先pushdown的lazy,如果此时+的lazy还在,那么改一下+的lazy即可,然后pushdown+的lazy就不用递归pushdown了
/**************************************************************
Problem: 1798
User: walfy
Language: C++
Result: Accepted
Time:5992 ms
Memory:38792 kb
****************************************************************/
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define ld long double
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
const double eps=1e-6;
const int N=400000+10,maxn=2000000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
ll val[N<<2],lazy[N<<2][2],p;
void pushup(int rt)
{
val[rt]=(val[rt<<1]+val[rt<<1|1])%p;
}
void pushdown(int l,int r,int rt)
{
int m=(l+r)>>1;
if(lazy[rt][0]!=1)
{
val[rt<<1]=val[rt<<1]*lazy[rt][0]%p;
val[rt<<1|1]=val[rt<<1|1]*lazy[rt][0]%p;
if(lazy[rt<<1][1]!=0)lazy[rt<<1][1]=lazy[rt<<1][1]*lazy[rt][0]%p;
lazy[rt<<1][0]=lazy[rt<<1][0]*lazy[rt][0]%p;
if(lazy[rt<<1|1][1]!=0)lazy[rt<<1|1][1]=lazy[rt<<1|1][1]*lazy[rt][0]%p;
lazy[rt<<1|1][0]=lazy[rt<<1|1][0]*lazy[rt][0]%p;
lazy[rt][0]=1;
}
if(lazy[rt][1]!=0)
{
val[rt<<1]=(val[rt<<1]+(m-l+1)*lazy[rt][1]%p)%p;
val[rt<<1|1]=(val[rt<<1|1]+(r-m)*lazy[rt][1]%p)%p;
// if(lazy[rt<<1][0]!=1&&l<r)pushdown(ls);
lazy[rt<<1][1]=(lazy[rt<<1][1]+lazy[rt][1])%p;
// if(lazy[rt<<1|1][0]!=1&&l<r)pushdown(rs);
lazy[rt<<1|1][1]=(lazy[rt<<1|1][1]+lazy[rt][1])%p;
lazy[rt][1]=0;
}
}
void build(int l,int r,int rt)
{
lazy[rt][0]=1;
if(l==r)
{
scanf("%lld",&val[rt]);
val[rt]%=p;
return ;
}
int m=(l+r)>>1;
build(ls);build(rs);
pushup(rt);
}
void update(int L,int R,ll c,int op,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
if(op==1)
{
if(lazy[rt][1]!=0)pushdown(l,r,rt);
val[rt]=val[rt]*c%p,lazy[rt][0]=lazy[rt][0]*c%p;
}
else
{
if(lazy[rt][0]!=1)pushdown(l,r,rt);
val[rt]=(val[rt]+(r-l+1)*c%p)%p;lazy[rt][1]=(lazy[rt][1]+c)%p;
}
return ;
}
pushdown(l,r,rt);
int m=(l+r)>>1;
if(L<=m)update(L,R,c,op,ls);
if(m<R)update(L,R,c,op,rs);
pushup(rt);
}
ll query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)return val[rt];
pushdown(l,r,rt);
int m=(l+r)>>1;
ll ans=0;
if(L<=m)ans=(ans+query(L,R,ls))%p;
if(m<R)ans=(ans+query(L,R,rs))%p;
return ans;
}
void debug(int l,int r,int rt)
{
printf("%d %d %lld %lld %lld\n",l,r,val[rt],lazy[rt][0],lazy[rt][1]);
if(l==r)return ;
int m=(l+r)>>1;
debug(ls);debug(rs);
}
int main()
{
int n;
scanf("%d%lld",&n,&p);
build(1,n,1);
int m;scanf("%d",&m);
while(m--)
{
// debug(1,n,1);puts("+++++++++++");
int op,l,r;
scanf("%d%d%d",&op,&l,&r);
if(op==1||op==2)
{
ll c;scanf("%lld",&c);
update(l,r,c,op,1,n,1);
}
else printf("%lld\n",query(l,r,1,n,1));
}
return 0;
}
/********************
********************/