Description
给定一个序列,你的任务是随时告诉他某段区间所有数的乘积,当然,他可不会给出一个这么简单的问题,为了让问题更有(e)趣(xin),他不时会修改其中某个元素的值。
Input
第1行,两个正整数n,m。
第2行,n个正整数,表示数列中元素的初值。
第3至m+2行,每行三个正整数p,x,y。
当p=1表示查询x到y区间内的数的乘积;
当p=2表示修改第x个数为y。
Output
对于每个询问输出一行,表示询问结果(模10^9+7)。
3 3 2 2 2 1 1 3 2 2 3 1 2 3
-
Sample Input
8 6
-
Sample Output
HINT
【数据规模】
对于30%的数据,满足1<=n,m<=1000;
对于100%的数据,满足1<=n,m<=100000,输入数据保证没有错误,且序列中的元素在任意时刻都不会超过100000。
很明显,线段树模板
#include <iostream>
#include <cstdio>
#define SIZE 400010
#define MOD (int (1e+09 + 7))
using namespace std;
typedef long long long_long; // 解决强制转换得到CE的某小bug
int res[SIZE];
void buildtree(int pos, int l, int r) // 建树
{
int mid;
if (l == r)
{
scanf("%d", &res[pos]);
return;
}
mid = l + r >> 1;
buildtree(pos << 1, l, mid);
buildtree((pos << 1) | 1, mid + 1, r);
res[pos] = (long_long (res[pos<<1]) * long_long (res[(pos<<1)+1])) % MOD; // 要强制转换!不然int溢出.
return;
}
void update(int pos, int l, int r, int x, int y) // 更新一个数
{
int mid;
if (l == r)
{
res[pos] = y;
return;
}
mid = l + r >> 1;
if (x <= mid)
{
update(pos << 1, l, mid, x, y);
}
else
{
update((pos << 1) | 1, mid + 1, r, x, y);
}
res[pos] = (long_long (res[pos<<1]) * long_long (res[(pos<<1)|1])) % MOD;
return;
}
int query(int pos, int l, int r, int x, int y) // 询问区间乘积
{
int t1, t2, mid;
if ((x <= l) && (y >= r))
{
return res[pos];
}
mid = l + r >> 1;
t1 = t2 = 1;
if (x <= mid)
{
t1 = query(pos << 1, l, mid, x, y);
}
if (y > mid)
{
t2 = query((pos << 1) | 1, mid + 1, r, x, y);
}
return (long_long (t1) * long_long (t2)) % MOD;
}
int main(void)
{
int n, m, p, x, y;
scanf("%d%d", &n, &m);
buildtree(1, 1, n);
while (m--)
{
scanf("%d%d%d", &p, &x, &y); // 操作编号和参数
if (p == 1)
{
printf("%d\n", query(1, 1, n, x, y));
}
else
{
update(1, 1, n, x, y);
}
}
return 0;
}