本文主要是介绍POJ 3468 A Simple Problem with Integers 【线段树,区间更新】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
题意:你有N个整数,A1,A2,…,一个。你需要处理两种类型的操作。一种类型的操作是添加了一些给定的数字,每个数字在一个给定的时间间隔。另一种是在给定的时间间隔要求数量的总和。
难点:主要是lazy标记,不好弄懂, 其实lazy标记就是当前改变的值不全部更新,等到用的时候再更新,这样就节省了好多时间。
题目链接:http://poj.org/problem?id=3468
代码:
#include<stdio.h>
#include<string.h>
#define MAXN 100005
#define LC l, m, rt<<1
#define RC m+1, r, rt<<1|1
#define LL __int64
LL sum[MAXN<<2], add[MAXN<<2];//add数组就是暂时储存要增加的
void pushup(int rt)
{sum[rt] = sum[rt<<1]+sum[rt<<1|1];
}
void pushdown(int rt, int m)//这个是难点,理解了这个这道题就差不多了
{if(add[rt]){add[rt<<1] += add[rt];add[rt<<1|1] += add[rt];sum[rt<<1] += add[rt]*(m-(m>>1));sum[rt<<1|1] += add[rt]*(m>>1);add[rt] = 0;}
}
void creat(int l,int r,int rt) {add[rt] = 0;if (l == r) {scanf("%I64d",&sum[rt]);return ;}int m = (l + r) >> 1;creat(LC);creat(RC);pushup(rt);
}
void update(int le, int ri, int num, int l, int r, int rt)
{if(le <= l&&r<=ri){add[rt] += num;sum[rt] += (LL)num*(r-l+1);return;}pushdown(rt, r-l+1);int m = (l+r)>>1;if(le <=m) update(le, ri, num, LC);if(ri > m) update(le, ri, num, RC);pushup(rt);
}
LL query(int le, int ri, int l, int r, int rt)
{if(le <= l&&r<=ri){return sum[rt];}pushdown(rt, r-l+1);LL res = 0;LL m = (l+r)>>1;if(le <= m) res += query(le, ri, LC);if(ri > m) res += query(le, ri, RC);return res;
}
int main()
{int n, m;scanf("%d%d", &n, &m);creat(1, n, 1);char s[2];int a, b, c;while(m --){scanf("%s", s);if(s[0] == 'Q'){scanf("%d%d", &a, &b);printf("%I64d\n", query(a, b, 1, n, 1));}else{scanf("%d%d%d", &a, &b, &c);update(a, b, c, 1, n, 1);}}return 0;
}
这篇关于POJ 3468 A Simple Problem with Integers 【线段树,区间更新】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!