ccnu-线段树-简单的区间更新(三题)
来源:互联网 发布:在国外如何淘宝买东西 编辑:程序博客网 时间:2024/05/16 07:22
题目一:http://poj.org/problem?id=3468
Description
You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C abc" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q ab" means querying the sum of Aa, Aa+1, ... , Ab.
Output
You need to answer all Q commands in order. One answer in a line.
Sample Input
10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4
Sample Output
4
55
9
15
Hint
The sums may exceed the range of 32-bit integers.
裸的区间更新,关于lazy标记,还是老话,在下一次更新或询问时才把区间信息传递(pushdown)下去。
代码:
#include<iostream>#include<cstdio>#include<string>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define Max 100020long long a,b,q,n;long long sum[Max<<2],c,lazy[Max<<2];void pushup(int rt){ sum[rt] = sum[rt<<1] + sum[rt<<1|1];}void pushdown(int rt,int m){ if(lazy[rt]) { lazy[rt<<1] += lazy[rt]; lazy[rt<<1|1] += lazy[rt]; sum[rt<<1] += lazy[rt] * (m - (m>>1)); sum[rt<<1|1] += lazy[rt] * (m>>1); lazy[rt] = 0; }}void build(int l,int r,int rt){ sum[rt] = 0; if(l == r) { scanf("%lld",&sum[rt]); return; } int m = (r + l)>>1; build(lson); build(rson); pushup(rt);}void Add(int L,int R,int v,int l,int r,int rt){ if(L <= l&&r <= R) { lazy[rt] += v; sum[rt] += (long long)(r - l + 1) * v; return ; } pushdown(rt,r-l+1); int m = (r + l)>>1; if(L <= m) Add(L,R,v,lson); if(m < R) Add(L,R,v,rson); pushup(rt);}long long query(int L,int R,int l,int r,int rt){ if(L <= l&&r <= R) { return sum[rt]; } long long rec = 0; int m = (r + l)>>1; pushdown(rt,r-l+1); if(L <= m) rec += query(L,R,lson); if(m < R) rec += query(L,R,rson); return rec;}int main(){ scanf("%d%d",&n,&q); build(1,n,1); while(q--) { char qus[2]; scanf("%s",&qus); if(qus[0] == 'C') { scanf("%d%d%d",&a,&b,&c); Add(a,b,c,1,n,1); } else { scanf("%d%d",&a,&b); printf("%lld\n",query(a,b,1,n,1)); } } return 0;}
题型二:http://acm.hdu.edu.cn/showproblem.php?pid=1698
把上题的求和改成更新区间值就可以了。
代码如下:
#include<iostream>#include<cstdio>#define Max 100010#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;int sum[Max<<2],lazy[Max<<2];void pushup(int rt){ sum[rt] = sum[rt<<1] + sum[rt<<1|1];}void pushdown(int rt,int INL){ if(lazy[rt]) { lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt]; sum[rt<<1] = lazy[rt] * (INL - (INL>>1)); sum[rt<<1|1] = lazy[rt] * (INL>>1); lazy[rt] = 0; }}void build(int l,int r,int rt){ lazy[rt] = 0; sum[rt] = 1; if(r == l) { return; } int m = (r + l) >> 1; build(lson); build(rson); pushup(rt);}void update(int L,int R,int val,int l,int r,int rt){ if(L <= l&&r <= R) { sum[rt] = val * (r-l+1); lazy[rt] = val; return; } pushdown(rt,r-l+1); int m = (r + l)>>1; if(L <= m) update(L,R,val,lson); if(m < R) update(L,R,val,rson); pushup(rt);}int main(){ int T,n,x,y,z,q; scanf("%d",&T); int lala = T; while(T--) { scanf("%d",&n); build(1,n,1); scanf("%d",&q); while(q--) { scanf("%d%d%d",&x,&y,&z); update(x,y,z,1,n,1); } printf("Case %d: The total value of the hook is %d.\n",(lala-T),sum[1]); } return 0;}
【题型三-hdu-ColorTheBall】http://acm.hdu.edu.cn/showproblem.php?pid=1556
题意:把a,b区间的 气球都涂上颜色,输出每个气球被涂色的次数。
思路:每次更新只记录到所更新的区间便不再往下记录更新,不需要pushup,只需要在输出时pushdown更新一次到每个节点就可以了
经验教训: 不要用cout, 不要用cout, 不要用cout!
#include<iostream>#include<cstdio>#include<algorithm>using namespace std;#define maxn 100010#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int lazy[maxn<<4]; int n;//int index[maxn];void build(int l, int r, int rt){ int m; m = (l + r)>>1; lazy[rt] = 0; if(l == r) return; build(lson); build(rson);}void pushdown(int rt){ if(lazy[rt]) { lazy[rt<<1] += lazy[rt]; lazy[rt<<1|1] += lazy[rt]; lazy[rt] = 0; }}void paint(int l, int r, int rt, int L, int R){ if(L <= l && r <= R) { lazy[rt]++; return ; } int m = (r+l)>>1; if(L <= m) paint(lson, L,R); if(m < R) paint(rson, L, R);}void finalQuery(int l, int r, int rt){ int m = (l+r)>>1; if(l == r) { printf("%d%c",lazy[rt],l==n?'\n':' '); return; } pushdown(rt); //在查询的时候才pushdown finalQuery(lson); finalQuery(rson);}int main(){ while(scanf("%d", &n) != EOF&&n) { build(1,n,1); for(int i = 0; i < n; i++) { int a, b; scanf("%d%d", &a, &b); paint(1, n, 1, a, b); //cout<<"-"<<endl; } finalQuery(1, n, 1); } return 0;}
- ccnu-线段树-简单的区间更新(三题)
- ccnu-线段树-单点更新3-C
- 线段树的区间更新
- 线段树的区间更新
- 琐碎的区间(线段树区间更新 + 技巧!)
- 线段树的区间更新区间合并
- poj 3468(简单线段树区间更新)
- CCNU-线段树练习题-A-单点更新1
- ccnu-线段树联系-单点更新2-B
- HDU1698 Just a Hook (简单的区间更新线段树)
- 线段树(单点更新+区间更新)
- 线段树、前缀数组:HDU1591-Color the ball(区间更新、简单题)
- 线段树区间更新
- 线段树区间更新
- 线段树 区间更新
- 线段树区间更新
- 线段树-区间更新
- 线段树区间更新
- 自定义语言的实现——解释器模式(三)
- 标注样式:创建、修改和置为当前
- 对数组进行排序、求最大值和求元素和的算法都编写为函数模板,采用相关数据进行测试。
- 自定义语言的实现——解释器模式(四)
- 自定义语言的实现——解释器模式(五)
- ccnu-线段树-简单的区间更新(三题)
- 记牌器教程 hook socket教程 c++
- jsp Servlet基础入门学习:设置HTTP应答头
- Awk - 教程
- 持久化状态与hibernate语句执行顺序
- Android常用功能汇总
- 基于VC++开发InlineHook网络数据发送接收函数
- python 文件操作(转载)
- 林仕鼎:架构师成长之路----如何突破瓶颈