您的位置:首页 > 其它

洛谷 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函数 运算优先级加法优先TAT

AC代码

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: