BZOJ1798 维护序列seq
1798: [Ahoi2009]Seq 维护序列seq
Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 8058 Solved: 2964
[Submit][Status][Discuss]
Description
老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。 有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。
Input
第一行两个整数N和P(1≤P≤1000000000)。第二行含有N个非负整数,从左到右依次为a1,a2,…,aN, (0≤ai≤1000000000,1≤i≤N)。第三行有一个整数M,表示操作总数。从第四行开始每行描述一个操作,输入的操作有以下三种形式: 操作1:“1 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai×c (1≤t≤g≤N,0≤c≤1000000000)。 操作2:“2 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai+c (1≤t≤g≤N,0≤c≤1000000000)。 操作3:“3 t g”(不含双引号)。询问所有满足t≤i≤g的ai的和模P的值 (1≤t≤g≤N)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。
Output
对每个操作3,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。
Sample Input
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
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
Sample Output
2
35
8
35
8
从中午写题开始一直写到晚上转钟,中间写了无数次bug和被自己手抖写错了一个地方
找bug真的是难受,以后这样就直接重新写吧
题意:线段树的查询、区间修改、sum和的操作
题解:从某大佬的专题学习了线段树在结构体里面的写法,在结构体里面创建树的话,就可以直接调用和查询
板子题了,用sum数组来存这颗树,每次插入操作对树上的每一段区间/节点都进行一次update
代码如下:
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int maxn = 8e5+5; long long mod; long long n,m; struct segtree{ #define lc(x) (x*2) #define rc(x) (x*2+1) long long l[maxn],r[maxn]; long long sumi[maxn],mul[maxn],add[maxn]; void build(int x,int L,int R){ //数组从1开始 l[x]=L; r[x]=R; add[x]=0; mul[x]=1; if(L==R){ //区间节点 cin>>sumi[x]; return; } int mid=(L+R)/2; build(lc(x),L,mid); build(rc(x),mid+1,R); update(x); } void update(int x){ sumi[x]=(sumi[lc(x)]+sumi[rc(x)])%mod; } void push(int x){ mul[lc(x)]=(mul[lc(x)]*mul[x])%mod; mul[rc(x)]=(mul[rc(x)]*mul[x])%mod; add[lc(x)]=(add[lc(x)]*mul[x]+add[x])%mod; add[rc(x)]=(add[rc(x)]*mul[x]+add[x])%mod; sumi[lc(x)]=(sumi[lc(x)]*mul[x]+ add[x]*(r[lc(x)]-l[lc(x)]+1))%mod; sumi[rc(x)]=(sumi[rc(x)]*mul[x]+ add[x]*(r[rc(x)]-l[rc(x)]+1))%mod; add[x]=0; mul[x]=1; } void ADD(int x,int L,int R,long long v){ push(x); if(R<l[x]||L>r[x]) return; //查询区间不在范围内 if(L<=l[x]&&r[x]<=R){ sumi[x]=(sumi[x]+v*(r[x]-l[x]+1))%mod; add[x]=(add[x]+v)%mod; return; } ADD(lc(x),L,R,v); ADD(rc(x),L,R,v); update(x); } void MUL(int x,int L,int R,long long v){ push(x); if(R<l[x]||L>r[x]) return; if(L<=l[x]&&r[x]<=R){ sumi[x]=(sumi[x]*v)%mod; add[x]=(add[x]*v)%mod; mul[x]=(mul[x]*v)%mod; return; } MUL(lc(x),L,R,v); MUL(rc(x),L,R,v); update(x); } long long Qsum(int x,int L,int R){ push(x); if(l[x]>R||r[x]<L) return 0; if(L<=l[x]&&r[x]<=R) return sumi[x]; return (Qsum(lc(x),L,R)+Qsum(rc(x),L,R))%mod; } }seg; int main(){ cin>>n>>mod; seg.build(1,1,n); cin>>m; for(long long i= 1,op,l,r;i<=m;i++){ cin>>op>>l>>r; if(op==3) { cout<<seg.Qsum(1,l,r)<<endl; } else{ long long v; cin>>v; if(op==1) seg.MUL(1,l,r,v); else seg.ADD(1,l,r,v); } } return 0; }
每一个不曾刷题的日子
都是对生命的辜负
从弱小到强大,需要一段时间的沉淀,就是现在了
~buerdepepeqi