线段树模板及习题
2017-10-04 10:56
141 查看
#include <iostream> #include <cstdio> #define lid (id << 1) #define rid (id << 1 | 1) using namespace std; const int N=100005; struct node { int l,r; long long sum; }tr[N * 4]; int a ; void push_up(int id)//求父节点,父节点对应的两个子节点分别是id<<2和id<<2|1 { tr[id].sum = tr[lid].sum + tr[rid].sum; } void build(int id, int l,int r) { tr[id].l = l; tr[id].r = r; if(l == r) { tr[id].sum = a[l]; return; } int mid = (l + r) >> 1; build(lid, l, mid); build(rid, mid + 1, r); push_up(id); } void updata(int id,int x,int v)//更改一个树叶节点的值 { if(tr[id].l == tr[id].r){ tr[id].sum = v; return; } int mid = (tr[id].l + tr[id].r) >> 1; updata(x <= mid ? lid : rid, x, v); push_up(id); } long long query(int id, int l, int r) { if(tr[id].l == l && tr[id].r == r) return tr[id].sum; int mid = (tr[id].l + tr[id].r) >> 1; if(r <= mid) return query(lid, l, r); if(l > mid) return query(rid, l, r); return query(lid, l, mid)+query(rid, mid + 1,r); } int main() { int n,m; int p,x,y; scanf("%d",&n); for(int i = 1;i <= n; i ++) scanf("%d",&a[i]); build(1,1,n); scanf("%d",&m); while(m--) { scanf("%d%d%d",&p,&x,&y); if(p == 1) updata(1, x, y); else printf("%lld\n",query(1,x,y)); } return 0; }
敌兵布阵
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 8754 Accepted Submission(s): 3647
[align=left]Problem Description[/align]
C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了。A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况。由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视。
中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时向Derek汇报某一段连续的工兵营地一共有多少人,例如Derek问:“Tidy,马上汇报第3个营地到第10个营地共有多少人!”Tidy就要马上开始计算这一段的总人数并汇报。但敌兵营地的人数经常变动,而Derek每次询问的段都不一样,所以Tidy不得不每次都一个一个营地的去数,很快就精疲力尽了,Derek对Tidy的计算速度越来越不满:"你个死肥仔,算得这么慢,我炒你鱿鱼!”Tidy想:“你自己来算算看,这可真是一项累人的工作!我恨不得你炒我鱿鱼呢!”无奈之下,Tidy只好打电话向计算机专家Windbreaker求救,Windbreaker说:“死肥仔,叫你平时做多点acm题和看多点算法书,现在尝到苦果了吧!”Tidy说:"我知错了。。。"但Windbreaker已经挂掉电话了。Tidy很苦恼,这么算他真的会崩溃的,聪明的读者,你能写个程序帮他完成这项工作吗?不过如果你的程序效率不够高的话,Tidy还是会受到Derek的责骂的.
[align=left]Input[/align]
第一行一个整数T,表示有T组数据。
每组数据第一行一个正整数N(N<=50000),表示敌人有N个工兵营地,接下来有N个正整数,第i个正整数ai代表第i个工兵营地里开始时有ai个人(1<=ai<=50)。
接下来每行有一条命令,命令有4种形式:
(1) Add i j,i和j为正整数,表示第i个营地增加j个人(j不超过30)
(2)Sub i j ,i和j为正整数,表示第i个营地减少j个人(j不超过30);
(3)Query i j ,i和j为正整数,i<=j,表示询问第i到第j个营地的总人数;
(4)End 表示结束,这条命令在每组数据最后出现;
每组数据最多有40000条命令
[align=left]Output[/align]
对第i组数据,首先输出“Case i:”和回车,
对于每个Query询问,输出一个整数并回车,表示询问的段中的总人数,这个数最多不超过1000000。
[align=left]Sample Input[/align]
1101 2 3 4 5 6 7 8 9 10Query 1 3Add 3 6Query 2 7Sub 10 2Add 6 3Query 3 10End
[align=left]Sample Output[/align]
Case 1:63359
[align=left]Author[/align]
Windbreaker
[align=left]Recommend[/align]
Eddy
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define lson (i<<1) #define rson (lson|1) int a[50007]; struct zz { int l,r,sum; } b[1000000]; void push_up(int i) { b[i].sum = b[lson].sum + b[rson].sum; } void build(int i,int l,int r) { b[i].l=l; b[i].r=r; if(l==r) { b[i].sum=a[l]; return ; } int mid=(l+r)/2; build(lson,l,mid); build(rson,mid+1,r); push_up(i); } void add(int i,int x,int y)// + { if(b[i].l == b[i].r) { b[i].sum += y; return; } int mid = (b[i].l + b[i].r)/2; if(x <= mid) add(lson, x, y); else add(rson, x, y); push_up(i); } void sub(int i,int id,int v)// - { if(b[i].l == b[i].r) { b[i].sum -= v; return; } int mid = (b[i].l + b[i].r)/2; if(id <= mid) sub(lson, id, v); else sub(rson, id, v); push_up(i); } int SUM(int i, int l, int r) { if(b[i].l ==l&&b[i].r == r) return b[i].sum; int mid=(b[i].l + b[i].r)/2; if(r <= mid) return SUM(lson, l, r); if(l > mid) return SUM(rson, l, r); return SUM(lson, l, mid)+SUM(rson, mid + 1,r); } int main() { int n,i,T,num; char s1[20]="Query",s2[20]="Sub",s3[20]="Add",s4[20]="End"; char str[16]; scanf("%d",&T);num=0; while(T--) { scanf("%d",&n); for(i=1; i<=n; i++) scanf("%d",&a[i]); build(1,1,n); printf("Case %d:\n",++num); while(scanf("%s",str)!=EOF) { if(strcmp(str,s1)==0) { int x,y; scanf("%d%d",&x,&y); printf("%d\n",SUM(1,x,y)); } if(strcmp(str,s2)==0)//- { int id,v; scanf("%d%d",&id,&v); sub(1,id,v); } if(strcmp(str,s3)==0)//+ { int id,v; scanf("%d%d",&id,&v); add(1,id,v); } if(strcmp(str,s4)==0) { break; } } } return 0; }
相关文章推荐
- KMP模板+习题
- 线段树详解+模板
- 线段树 模板 及 解释
- 可持久化线段树 (模板)
- 线段树模板
- 线段树模板
- HDU 1166 敌兵布阵(线段树模板)
- 线段树模板
- 线段树 模板
- HDU-1754 I Hate It (线段树裸题 splay模板 单点修改 区间询问最大值)
- 线段树模板及解释
- 【模板】可持久化线段树(主席树)
- hdu 1166 敌兵布阵(线段树模板题)
- HDU 1166 线段树模板&树状数组模板
- 线段树模板
- 【模板】线段树 1
- 模板——线段树(区间修改)
- Hihocoder #1077 : RMQ问题再临-线段树(线段树:结构体建树+更新叶子往上+查询+巧妙使用father[]+线段树数组要开大4倍 *【模板】)
- 线段树模板
- 【线段树】模板-HDU-1166-点改区查