1080 线段树练习
2016-08-02 08:53
260 查看
题目描述 Description
一行N个方格,开始每个格子里都有一个整数。现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和;修改的规则是指定某一个格子x,加上或者减去一个特定的值A。现在要求你能对每个提问作出正确的回答。1≤N<100000,,提问和修改的总数m<10000条。输入描述 Input Description
输入文件第一行为一个整数N,接下来是n行n个整数,表示格子中原来的整数。接下一个正整数m,再接下来有m行,表示m个询问,第一个整数表示询问代号,询问代号1表示增加,后面的两个数x和A表示给位置X上的数值增加A,询问代号2表示区间求和,后面两个整数表示a和b,表示要求[a,b]之间的区间和。
输出描述 Output Description
共m行,每个整数样例输入 Sample Input
64
5
6
2
1
3
4
1 3 5
2 1 4
1 1 9
2 2 6
样例输出 Sample Output
2222
数据范围及提示 Data Size & Hint
1≤N≤100000, m≤10000 。裸裸的线段树,单点修改+区间求和。
线段树代码
#include<cstdio> #include<iostream> #include<cstring> using namespace std; #define M 1000010 #define lch now*2 #define rch now*2+1 #define smid (l+r)/2 int a[M]; struct node { int l,r,sum; };node sgt[M]; void build(int now,int l,int r)//建树 { sgt[now].l=l; sgt[now].r=r; if(l==r) { sgt[now].sum=a[l]; return; } build(lch,l,smid); build(rch,smid+1,r); sgt[now].sum=sgt[lch].sum+sgt[rch].sum; } void modify(int now,int pos,int l,int r,int v)//修改 { if(l==r) { sgt[now].sum+=v; return; } if(pos<=smid) modify(lch,pos,l,smid,v); else modify(rch,pos,smid+1,r,v); sgt[now].sum=sgt[lch].sum+sgt[rch].sum; } int query(int now,int l,int r,int x,int y) { if(l==x&&r==y) return sgt[now].sum; if(y<=smid)return query(lch,l,smid,x,y); else if(x>smid)return query(rch,smid+1,r,x,y); else return query(lch,l,smid,x,smid)+query(rch,smid+1,r,smid+1,y); } int main() { int n,m,flag,x,y; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n); scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d%d%d",&flag,&x,&y); if(flag==1)modify(1,x,1,n,y); else printf("%d\n",query(1,1,n,x,y)); } return 0; }
听说还有树状数组,比线段树更快,所以请教某犇打了一个,
只用30ms就过了…..
树状数组代码
#include<iostream> #include<cstdio> #define MAXN 100001 using namespace std; int n,m,s[MAXN]; int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-48,ch=getchar(); return x*f; } int lowbit(int t){ return t&-t; } void add(int x,int data){ while(x<=n){ s[x]+=data; x+=lowbit(x); } } int query(int x){ int tot=0; while(x){ tot+=s[x]; x-=lowbit(x); } return tot; } int main() { int x,y,z,v; n=read(); for(int i=1;i<=n;i++) x=read(),add(i,x); m=read(); while(m--){ z=read(); if(z==1){ x=read();y=read(); add(x,y); } else { x=read();y=read(); printf("%d\n",query(y)-query(x-1)); } } return 0; }
相关文章推荐
- 【codevs 1080】线段树练习
- codevs1080 线段树练习
- 1080 线段树练习 codevs
- 1080 线段树练习 单点修改及区间查询
- codevs 1080 线段树练习
- codevs 1080_线段树练习_树状数组
- codevs 1080~1082 线段树练习系列(模板)
- [题解] codevs 1080 线段树练习
- <线段树系列1> codevs 1080 线段树练习
- codevs 1080 线段树练习
- CODEVS 1080 线段树练习
- [Codevs] 1080 线段树练习
- CODEVS 1080线段树练习
- codevs 1080 线段树练习--用树状数组做的
- Wiki OI 1080 线段树练习
- 【数据结构】树状数组模板--CODE[VS] 1080线段树练习and1081线段树练习2
- codevs 1080 线段树练习
- 水题笔记:codevs 1080 线段树练习 [重口味线段树初次(单点修改)]
- 1080 线段树练习
- 【codevs 1080~1082】线段树练习重做