bzoj1798维护序列
试题描述
|
老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。
有长为 N 的数列,不妨设为 a1,a2,⋯,an。有如下三种操作: ①把数列中的一段数全部乘一个值; ②把数列中的一段数全部加一个值; ③询问数列中的一段数的和,由于结果可能很大,你只需输出这个数模 P 的值。 |
输入
|
第一行两个整数 N 和 P(1≤P≤1000000000)。第二行含有 N 个非负整数,从左到右依次为 a1,a2,⋯,aN,(0≤ai≤1000000000,1≤i≤N)。第三行有一个整数 M,表示操作总数。从第四行开始每行描述一个操作,输入的操作有以下三种形式:
操作1:“1 t g c”(不含双引号)。表示把所有满足 t≤i≤gt 的 ai 改为ai*c(1≤t≤gN,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)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。 |
输出
|
对每个操作 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 |
线段树还是板子,维护的时候一定要多注意取模
然后要注意,写pushdown的时候一定要特判,否则会T
下面给出出代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> using namespace std; inline long long rd(){ long long x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) x=(x<<3)+(x<<1)+ch-'0'; return x*f; } inline void write(long long x){ if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0'); return ; } struct node{ long long l,r; long long sum; long long f1,f2; }tree[4000006]; long long n,mod,m; inline void build(long long i,long long x,long long y){ tree[i].l=x,tree[i].r=y; tree[i].f2=1; if(x==y){ tree[i].sum=rd(); return ; } long long mid=(x+y)>>1; build(i<<1,x,mid); build(i<<1|1,mid+1,y); tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum; return ; } inline void pushdown(long long x){ long long h1=tree[x].f1%mod,h2=tree[x].f2%mod; if(!h1&&h2==1) return ; tree[x<<1].sum=tree[x<<1].sum*h2+(tree[x<<1].r-tree[x<<1].l+1)*h1,tree[x<<1].sum%=mod; tree[x<<1|1].sum=tree[x<<1|1].sum*h2+(tree[x<<1|1].r-tree[x<<1|1].l+1)*h1,tree[x<<1|1].sum%=mod; tree[x<<1].f2*=h2,tree[x<<1|1].f2*=h2; tree[x<<1].f2%=mod,tree[x<<1|1].f2%=mod; tree[x<<1].f1*=h2,tree[x<<1].f1+=h1,tree[x<<1].f1%=mod; tree[x<<1|1].f1*=h2,tree[x<<1|1].f1+=h1,tree[x<<1|1].f1%=mod; tree[x].f1=0,tree[x].f2=1; return ; } inline void add(long long i,long long x,long long y,long long z){ if(tree[i].l>=x&&tree[i].r<=y){ tree[i].f1+=z,tree[i].f1%=mod; tree[i].sum+=(tree[i].r-tree[i].l+1)*z,tree[i].sum%=mod; return ; } pushdown(i); if(tree[i<<1].r>=x) add(i<<1,x,y,z); if(tree[i<<1|1].l<=y) add(i<<1|1,x,y,z); tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum,tree[i].sum%=mod; return ; } inline void mul(long long i,long long x,long long y,long long z){ if(tree[i].l>=x&&tree[i].r<=y){ tree[i].f2*=z;tree[i].f2%=mod; tree[i].f1*=z;tree[i].f1%=mod; tree[i].sum*=z;tree[i].sum%=mod; return ; } pushdown(i); if(tree[i<<1].r>=x) mul(i<<1,x,y,z); if(tree[i<<1|1].l<=y) mul(i<<1|1,x,y,z); tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum,tree[i].sum%=mod; return ; } inline long long solve(long long i,long long x,long long y){ if(tree[i].l>=x&&tree[i].r<=y) return tree[i].sum%mod; pushdown(i); long long num=0; if(tree[i<<1].r>=x) num+=solve(i<<1,x,y),num%=mod; if(tree[i<<1|1].l<=y) num+=solve(i<<1|1,x,y),num%=mod; return num; } int main(){ n=rd(),mod=rd(); build(1,1,n); m=rd(); while(m--){ long long f=rd(); if(f==1){ long long x=rd(),y=rd(),z=rd(); mul(1,x,y,z); } if(f==2){ long long x=rd(),y=rd(),z=rd(); add(1,x,y,z); } if(f==3){ long long x=rd(),y=rd(); write(solve(1,x,y)%mod),puts(""); } } return 0; }
蒟蒻总是更懂你✿✿ヽ(°▽°)ノ✿