hihoCoder#1116-计算[线段树+合并区间]
2017-03-21 16:55
337 查看
时间限制:4000ms
单点时限:1000ms
内存限制:256MB
现在有一个有n个元素的数组a1, a2,
..., an。
记f(i, j) = ai * ai+1 *
... * aj。
初始时,a1 = a2 =
... = an = 0,每次我会修改一个ai的值,你需要实时反馈给我
∑1 <= i <= j <= n f(i, j)的值 mod 10007。
第一行包含两个数n(1<=n<=100000)和q(1<=q<=500000)。
接下来q行,每行包含两个数i, x,代表我把ai的值改为了x。
分别输出对应的答案,一个答案占一行。
样例输入
样例输出
题意:求所有子区间乘积之和。
思路:线段树可在logn时间复杂度内完成对区间的修改与查询。不过,这道题要定义一个数据结构
all:题目答案,lseg:区间所有前缀乘积之和,rseg:区间所有后缀乘积之和,mul:区间所有元素乘积。下面请看一组例子加深对本数据结构的理解。
例:
[3 4 2 5]
all:3 + 3*4 + 4*2 + 2*5 + 3*4*2 + 4*2*5 + 3*4*2*5
lseg:3 + 3*4 + 3*4*2 + 3*4*2*5
rseg:3*4*2*5 + 4*2*5 + 2*5 + 5
mul:3*4*2*5
那么,区间是这样合并的:
下面是AC代码:
单点时限:1000ms
内存限制:256MB
描述
现在有一个有n个元素的数组a1, a2,..., an。
记f(i, j) = ai * ai+1 *
... * aj。
初始时,a1 = a2 =
... = an = 0,每次我会修改一个ai的值,你需要实时反馈给我
∑1 <= i <= j <= n f(i, j)的值 mod 10007。
输入
第一行包含两个数n(1<=n<=100000)和q(1<=q<=500000)。接下来q行,每行包含两个数i, x,代表我把ai的值改为了x。
输出
分别输出对应的答案,一个答案占一行。样例输入
5 5 1 1 2 1 3 1 4 1 5 1
样例输出
1 3 6 10 15
题意:求所有子区间乘积之和。
思路:线段树可在logn时间复杂度内完成对区间的修改与查询。不过,这道题要定义一个数据结构
struct Node { int l, r; _long all, lseg, rseg, mul; }
all:题目答案,lseg:区间所有前缀乘积之和,rseg:区间所有后缀乘积之和,mul:区间所有元素乘积。下面请看一组例子加深对本数据结构的理解。
例:
[3 4 2 5]
all:3 + 3*4 + 4*2 + 2*5 + 3*4*2 + 4*2*5 + 3*4*2*5
lseg:3 + 3*4 + 3*4*2 + 3*4*2*5
rseg:3*4*2*5 + 4*2*5 + 2*5 + 5
mul:3*4*2*5
那么,区间是这样合并的:
a[rt].all = (a[rt << 1].all + a[(rt << 1) | 1].all + a[rt << 1].rseg * a[(rt << 1) | 1].lseg) % MOD; a[rt].lseg = (a[rt << 1].lseg + a[rt << 1].mul * a[(rt << 1) | 1].lseg) % MOD; a[rt].rseg = (a[(rt << 1) | 1].rseg + a[(rt << 1) | 1].mul * a[rt << 1].rseg) % MOD; a[rt].mul = (a[rt << 1].mul * a[(rt << 1) | 1].mul) % MOD;
下面是AC代码:
#include <cstdio>
using namespace std;
const int MAXN = 100005;
const int MOD = 10007;
typedef long long _long;
struct Node { int l, r; _long all, lseg, rseg, mul; }a[MAXN * 3];
int n, q;
void pushUp(int rt) {
a[rt].all = (a[rt << 1].all + a[(rt << 1) | 1].all + a[rt << 1].rseg * a[(rt << 1) | 1].lseg) % MOD; a[rt].lseg = (a[rt << 1].lseg + a[rt << 1].mul * a[(rt << 1) | 1].lseg) % MOD; a[rt].rseg = (a[(rt << 1) | 1].rseg + a[(rt << 1) | 1].mul * a[rt << 1].rseg) % MOD; a[rt].mul = (a[rt << 1].mul * a[(rt << 1) | 1].mul) % MOD;
}
void build(int rt, int l, int r) {
a[rt].l = l;
a[rt].r = r;
if (l == r) {
a[rt].all = a[rt].lseg = a[rt].rseg = a[rt].mul = 0;
return ;
}
int mid = (l + r) >> 1;
build(rt << 1, l, mid);
build((rt << 1) | 1, mid + 1, r);
pushUp(rt);
}
void update(int rt, int pos, long val) {
if (a[rt].l == pos && a[rt].r == pos) {
a[rt].all = a[rt].lseg = a[rt].rseg = a[rt].mul = val;
return ;
}
int mid = (a[rt].l + a[rt].r) >> 1;
if (pos <= mid) {
update(rt << 1, pos, val);
} else {
update((rt << 1) | 1, pos, val);
}
pushUp(rt);
}
int main() {
while (scanf("%d%d", &n, &q) != EOF) {
build(1, 1, n);
while (q--) {
int pos;
_long x;
scanf("%d%lld", &pos, &x);
update(1, pos, x % MOD);
printf("%lld\n", a[1].all);
}
}
return 0;
}
相关文章推荐
- hihoCoder - 1116 - 计算 (线段树区间合并)
- hihoCoder 1116 计算 线段树 + 区间合并
- hihocoder 1116 : 计算(线段树 区间合并)
- hihocoder-1116 : 计算 (线段树区间合并)
- POJ 2892 Tunnel Warfare 区间合并线段树
- HDU 3308——LCIS(线段树,区间合并,最长连续递增子序列)
- 【HDU - 1540】Tunnel Warfare 【线段树+单点更新+区间合并】
- POJ 3667 Hotel 【线段树 区间合并】
- CodeForces - 145E - Lucky Queries(线段树[区间合并])
- UVA-11235-线段树加区间合并
- hdu3397Sequence operation(线段树区间合并)
- POJ 3667 - Hotel (线段树 区间合并)
- HDU1540 Tunnel Warfare(线段树区间合并)
- 线段树·POJ-3667·Hotel···区间合并
- POJ2667 Hotel(线段树区间合并)
- POJ 3667 Hotel (线段树区间合并)
- 约会安排 - HDU 4553 - 线段树 - 区间合并
- (两种解法)hdu 1540 Tunnel Warfare (线段树区间合并)
- POJ 3667 Hotel 线段树(区间合并)
- hdu3911 Black And White(线段树区间合并)