洛谷 P3373 【模板】线段树 2
2018-03-05 08:33
330 查看
P3373 【模板】线段树 2
题目描述
如题,已知一个数列,你需要进行下面三种操作: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
题意
改了好长时间的pushdown函数 运算优先级加法优先TATAC代码
#include <bits/stdc++.h> using namespace std; #define LL long long #define CLR(a,b) memset(a,(b),sizeof(a)) #define ls st<<1 #define rs st<<1|1 const LL MAXN = 1e6+10; LL a[MAXN]; LL n, m, p; struct node { LL l, r; LL len; LL val, mul, add; }tree[MAXN]; void build(LL l, LL f24c r, LL st) { tree[st].l = l, tree[st].r = r; tree[st].mul = 1, tree[st].add = 0; tree[st].len = r-l+1; if(l == r) { tree[st].val = a[l]; return ; } else { LL mid = (l+r)>>1; build(l,mid,ls); build(mid+1,r,rs); tree[st].val = tree[ls].val+tree[rs].val; } tree[st].val %= p; return ; } void push_down(LL st) { // if(tree[st].mul!=1) { // tree[ls].mul = (tree[st].mul*tree[ls].mul)%p; // tree[rs].mul = (tree[st].mul*tree[rs].mul)%p; // tree[ls].val = (tree[st].mul*tree[ls].val+tree[st].add*tree[ls].len)%p; // tree[rs].val = (tree[st].mul*tree[rs].val+tree[st].add*tree[rs].len)%p; // tree[st].mul = 1; // } // if(tree[st].add) { // tree[ls].add = (tree[ls].add*tree[st].mul+tree[st].add)%p; // tree[rs].add = (tree[rs].add*tree[st].mul+tree[st].add)%p; // tree[ls].val = (tree[st].mul*tree[ls].val+tree[st].add*tree[ls].len)%p; // tree[rs].val = (tree[st].mul*tree[rs].val+tree[st].add*tree[rs].len)%p; // tree[st].add = 0; //tree[st].mul = 1; // } tree[rs].add = (tree[rs].add*tree[st].mul+tree[st].add)%p; tree[ls].add = (tree[ls].add*tree[st].mul+tree[st].add)%p; tree[ls].mul = (tree[st].mul*tree[ls].mul)%p; tree[rs].mul = (tree[st].mul*tree[rs].mul)%p; tree[ls].val = (tree[st].mul*tree[ls].val+tree[st].add*tree[ls].len)%p; tree[rs].val = (tree[st].mul*tree[rs].val+tree[st].add*tree[rs].len)%p; tree[st].add = 0; tree[st].mul = 1; } void update_1(LL l, LL r,LL st, LL k) { if(l<=tree[st].l && r>=tree[st].r) { tree[st].val = (tree[st].val*k)%p; tree[st].mul = (tree[st].mul*k)%p; tree[st].add = (tree[st].add*k)%p; return ; } if(l>tree[st].r || r<tree[st].l) return ; push_down(st); update_1(l,r,ls,k); update_1(l,r,rs,k); tree[st].val = (tree[ls].val+tree[rs].val)%p; return ; } void update_2(LL l, LL r, LL st, LL k) { if(l<=tree[st].l && r>=tree[st].r) { tree[st].val = (tree[st].val+k*(tree[st].len))%p; tree[st].add = (tree[st].add+k)%p; return ; } if(l>tree[st].r || r<tree[st].l) return ; push_down(st); update_2(l,r,ls,k); update_2(l,r,rs,k); tree[st].val = (tree[ls].val+tree[rs].val)%p; return ; } LL query(LL l, LL r, LL st) { if(l<=tree[st].l && r >= tree[st].r) return tree[st].val; if(l>tree[st].r || r<tree[st].l) return 0; push_down(st); return (query(l,r,ls)+query(l,r,rs))%p; } int main() { ios::sync_with_stdio(false); cin >> n >> m >> p; for(LL i = 1; i <= n; i++) cin >> a[i]; build(1,n,1); while(m--) { LL q; LL x, y, k; cin >> q; if(q == 1) { cin >> x >> y >> k; update_1(x,y,1,k); } if(q == 2) { cin >> x >> y >> k; update_2(x,y,1,k); } if(q == 3) { cin >> x >> y; cout << query(x,y,1) << endl; } } return 0; }
相关文章推荐
- AC日记——【模板】线段树 2 洛谷 P3373
- 洛谷P3373 [ 模板] 线段树 (乘法和加法)
- 洛谷 P3373 【模板】线段树 2 (线段树)
- 洛谷P3373 【模板】线段树2
- 洛谷 P3372【模板】线段树 1
- 洛谷P3374模板线段树1
- 洛谷 P3372 线段树【模板1】
- 洛谷 P3372 【模板】线段树 1
- 洛谷P3380 【模板】二逼平衡树(树套树,树状数组,线段树)
- 洛谷.3834.[模板]可持久化线段树(主席树 静态区间第k小)
- P3373 【模板】线段树 2 区间求和 区间乘 区间加
- 洛谷 P3372 线段树模板
- 洛谷 P3372 【模板】线段树 1
- 洛谷1908 逆序对 权值线段树模板
- 洛谷 3372_【模板】线段树 1_线段树
- [洛谷3373]【模板】线段树 2
- 洛谷-P3373 线段树 2(线段树,区间更新,lazy标记,好题)
- 【Splay】洛谷3372 【模板】线段树 1
- P3373 【模板】线段树 2
- 【洛谷3834】 【模板】可持久化线段树 (主席树)