AC日记——【模板】线段树 2 洛谷 P3373
P3373 【模板】线段树 2
387
通过
1.8K
提交
标签
难度 提高+/省选-
提交 讨论 题解
最新讨论 更多讨论
2333
最后三个点卡常数。
迷之RE
感觉这题很迷啊
好像一共三组测试数据。
友情提示:开long long
题目描述
如题,已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数加上x
2.将某区间每一个数乘上x
3.求出某区间每一个数的和
输入输出格式
输入格式:
第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k
操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k
操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果
输出格式:
输出包含若干行整数,即为所有操作3的结果。
输入输出样例
输入样例#1:
5 5 38
1 5 4 2 3
2 1 4 1
3 2 5
1 2 4 2
2 3 5 5
3 1 4
输出样例#1:
17
2
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
(数据已经过加强^_^)
样例说明:
故输出应为17、2(40 mod 38=2)
思路:
裸线段树;
来,上代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define maxn 100005 #define LL long long using namespace std; struct TreeNodeType { LL l,r,dis,mid,flag,flag_; bool if_; }; struct TreeNodeType tree[maxn<<2],*lc,*rc; LL if_z,n,m,type,x,p,ans; char Cget; inline void in(LL &now) { now=0,if_z=1,Cget=getchar(); while(Cget>'9'||Cget<'0') { if(Cget=='-') if_z=-1; Cget=getchar(); } while(Cget>='0'&&Cget<='9') { now=now*10+Cget-'0'; Cget=getchar(); } now*=if_z; } void tree_build(LL now,LL l,LL r) { tree[now].l=l,tree[now].r=r; if(l==r) { in(tree[now].dis); return ; } tree[now].mid=(l+r)>>1; tree_build(now<<1,l,tree[now].mid); tree_build(now<<1|1,tree[now].mid+1,r); tree[now].dis=(tree[now<<1].dis+tree[now<<1|1].dis)%p; } void tree_do(LL now,LL l,LL r) { if(tree[now].l==l&&tree[now].r==r) { if(type==1) { tree[now].dis=(tree[now].dis*x)%p; tree[now].flag=(tree[now].flag*x)%p; if(tree[now].if_) tree[now].flag_=(tree[now].flag_*x)%p; else { tree[now].if_=true; tree[now].flag_=x; } } else if(type==2) { tree[now].flag=(tree[now].flag+x)%p; tree[now].dis=(tree[now].dis+((r-l+1)*x)%p)%p; } else ans=(ans+tree[now].dis)%p; return ; } if(tree[now].flag||tree[now].if_) { lc=&tree[now<<1],rc=&tree[now<<1|1]; if(tree[now].if_) { lc->dis=(lc->dis*tree[now].flag_)%p; rc->dis=(rc->dis*tree[now].flag_)%p; lc->flag=(lc->flag*tree[now].flag_)%p; rc->flag=(rc->flag*tree[now].flag_)%p; if(lc->if_) lc->flag_=(lc->flag_*tree[now].flag_)%p; else lc->flag_=tree[now].flag_,lc->if_=true; if(rc->if_) rc->flag_=(rc->flag_*tree[now].flag_)%p; else rc->flag_=tree[now].flag_,rc->if_=true; tree[now].if_=false; } if(tree[now].flag) { lc->flag=(lc->flag+tree[now].flag)%p; rc->flag=(rc->flag+tree[now].flag)%p; lc->dis=(lc->dis+((lc->r-lc->l+1)%p)*tree[now].flag)%p; rc->dis=(rc->dis+((rc->r-rc->l+1)%p)*tree[now].flag)%p; tree[now].flag=0; } } if(l>tree[now].mid) tree_do(now<<1|1,l,r); else if(r<=tree[now].mid) tree_do(now<<1,l,r); else { tree_do(now<<1,l,tree[now].mid); tree_do(now<<1|1,tree[now].mid+1,r); } tree[now].dis=(tree[now<<1].dis+tree[now<<1|1].dis)%p; } int main() { in(n),in(m),in(p);LL l,r; tree_build(1,1,n); while(m--) { in(type),in(l),in(r); if(type==1||type==2) in(x),tree_do(1,l,r); else { ans=0; tree_do(1,l,r); printf("%lld\n",ans); } } return 0; }