codevs 2216 行星序列 线段树+延迟标记(BZOJ 1798)
Posted xjhz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codevs 2216 行星序列 线段树+延迟标记(BZOJ 1798)相关的知识,希望对你有一定的参考价值。
2216 行星序列
“神州“载人飞船的发射成功让小可可非常激动,他立志长大后要成为一名宇航员假期一始,他就报名参加了“小小宇航员夏令营”,在这里小可可不仅学到了丰富的宇航知识,还参与解决了一些模拟飞行中发现的问题,今天指导老师交给他一个任务,在这次模拟飞行的路线上有N个行星,暂且称它们为一个行星序列,并将他们从1至n标号,在宇宙未知力量的作用下这N个行星的质量是不断变化的,所以他们对飞船产生的引力也会不断变化,小可可的任务就是在飞行途中计算这个行星序列中某段行星的质量和,以便能及时修正飞船的飞行线路,最终到达目的地,行星序列质量变化有两种形式:
1,行星序列中某一段行星的质量全部乘以一个值
2,行星序列中某一段行星的质量全部加上一个值
由于行星的质量和很大,所以求出某段行星的质量和后只要输出这个值模P的结果即可,小可可被这个任务难住了,聪明的你能够帮他完成这个任务吗?
第一行两个整数N和P(1<=p<=1000000000);
第二行含有N个非负整数,从左到右依次为a1,a2,…………,an(0<=ai<=100000000,1<=i<=n),其中ai表示第i个行星的质量:
第三行有一个整数m,表示模拟行星质量变化以及求质量和等操作的总次数。从第四行开始每行描述一个操作,输入的操作有以下三种形式:
操作1:1 t g c 表示把所有满足t<=i<=g的行星质量ai改为ai*c
操作2:2 t g c 表示把所有满足t<=i<=g的行星质量ai改为ai+c
操作3:3 t g 表示输出所有满足t<=i<=g的ai的和模p的值
其中:1<=t<=g<=N,0<=c<=10000000
注:同一行相邻的两数之间用一个空格隔开,每行开头和末尾没有多余空格
对每个操作3,按照它在输入中出现的顺序,依次一行输出一个整数表示所求行星质量和
7 43 1 2 3 4 5 6 7 5 1 2 5 5 3 2 4 2 3 7 9 3 1 3 3 4 7
2 35 8
100%的数据中,M,N<=100000
40%的数据中,M,N<=10000
思路:看了别人的题解(x + add) * mul = x * mul + add * mul;
#include<bits/stdc++.h> using namespace std; #define ll long long //#define mod 1000000007 #define pi (4*atan(1.0)) const int N=4e3+10,M=1e6+10,inf=1e9+10; ll sum[M]; ll flagj[M]; ll flagc[M]; ll mul(ll x,ll y,ll mod) { x%=mod; y%=mod; return (x*y)%mod; } void pushdown(ll pos,ll len,ll mod) { ll lson=pos*2; ll rson=pos*2+1; flagj[lson]=(flagj[lson]*flagc[pos]+flagj[pos])%mod; flagj[rson]=(flagj[rson]*flagc[pos]+flagj[pos])%mod; flagc[lson]=(flagc[pos]*flagc[lson])%mod; flagc[rson]=(flagc[pos]*flagc[rson])%mod; sum[lson]=mul(len-(len>>1),flagj[pos],mod)+sum[lson]*flagc[pos]; sum[lson]%=mod; sum[rson]=mul((len>>1),flagj[pos],mod)+sum[rson]*flagc[pos]; sum[rson]%=mod; flagj[pos]=0; flagc[pos]=1; } void buildtree(ll l,ll r,ll pos,ll mod) { flagc[pos]=1; flagj[pos]=0; if(l==r) { scanf("%lld",&sum[pos]); sum[pos]%=mod; return; } ll mid=(l+r)>>1; buildtree(l,mid,pos*2,mod); buildtree(mid+1,r,pos*2+1,mod); sum[pos]=sum[pos*2]+sum[pos*2+1]; sum[pos]%=mod; } ll query(ll L,ll R,ll l,ll r,ll pos,ll mod) { if(L<=l&&r<=R) return sum[pos]%mod; pushdown(pos,(r-l+1),mod); ll mid=(l+r)>>1; ll ans=0; if(L<=mid)ans+=query(L,R,l,mid,pos*2,mod); if(mid<R)ans+=query(L,R,mid+1,r,pos*2+1,mod); return ans%=mod; } void update(ll L,ll R,ll change,ll l,ll r,ll pos,ll flag,ll mod) { if(L<=l&&r<=R) { if(flag==1ll) { flagj[pos]*=change; flagj[pos]%=mod; flagc[pos]*=change; flagc[pos]%=mod; sum[pos]=mul(sum[pos],change,mod); } else { flagj[pos]+=change; flagj[pos]%=mod; sum[pos]+=mul(r-l+1,change,mod); sum[pos]%=mod; } return; } pushdown(pos,r-l+1,mod); ll mid=(l+r)/2; if(L<=mid)update(L,R,change,l,mid,pos*2,flag,mod); if(R>mid)update(L,R,change,mid+1,r,pos*2+1,flag,mod); sum[pos]=sum[pos*2]+sum[pos*2+1]; sum[pos]%=mod; } int main() { ll x,y,z,i,t; while(~scanf("%lld%lld",&x,&y)) { buildtree(1,x,1,y); ll q; scanf("%lld",&q); for(i=0;i<q;i++) { ll flag,l,r; scanf("%lld%lld%lld",&flag,&l,&r); if(flag==3ll) { printf("%lld\n",query(l,r,1,x,1,y)); } else { ll c; scanf("%lld",&c); update(l,r,c,1,x,1,flag,y); } } } return 0; }
以上是关于codevs 2216 行星序列 线段树+延迟标记(BZOJ 1798)的主要内容,如果未能解决你的问题,请参考以下文章
COGS.1272.[AHOI2009]行星序列(线段树 区间加乘求和)