基础线段树是一些基本操作之间的组合:
基本操作:单点更新、单点查询、区间更新,区间求和、区间最值
1、单点增减,区间求和
http://acm.hdu.edu.cn/showproblem.php?pid=1166
#include<algorithm> #include<cstring> #include<cstdio> #define MAXN 500000 using namespace std; struct SegTree { int left,right; int anssum; }tree[MAXN<<2]; void build(int root,int a,int b) { tree[root].left=a; tree[root].right=b; tree[root].anssum=0; if(a<b) { int M=(a+b)>>1; build(root<<1,a,M); build(root<<1|1,M+1,b); } } void update(int root,int i,int e)//单点增减 { int L,M,R; L=tree[root].left; R=tree[root].right; tree[root].anssum+=e; if(L==R) return ; M=(L+R)>>1; if(i<=M) update(root<<1,i,e); else update(root<<1|1,i,e); } int query(int root,int a,int b)//区间求和 { int L,M,R; L=tree[root].left; R=tree[root].right; M=(L+R)>>1; if(a==L&&b==R) return tree[root].anssum; if(b<=M) return query(root<<1,a,b); else if(a>M) return query(root<<1|1,a,b); else return query(root<<1,a,M)+query(root<<1|1,M+1,b); } int main() { int test,n,i,a,b,k=1; char s[5]; scanf("%d",&test); while(test--) { scanf("%d",&n); build(1,1,n); for(i=1;i<=n;i++) { scanf("%d",&a); update(1,i,a); } printf("Case %d:\n",k++); while(scanf("%s",s)&&strcmp(s,"End")!=0) { scanf("%d %d",&a,&b); if(s[0]=='Q') printf("%d\n",query(1,a,b)); else if(s[0]=='A') update(1,a,b); else update(1,a,-b); } } return 0; }
2、区间更新、单点访问
http://acm.nyist.net/JudgeOnline/problem.php?pid=123
#include<algorithm> #include<cstring> #include<cstdio> #define MAXN 1000000 using namespace std; struct SegTree { int left,right; int acount; } tree[MAXN<<2]; void build(int root,int a,int b) { tree[root].left=a; tree[root].right=b; tree[root].acount=0; if(a<b) { int M=(a+b)>>1; build(root<<1,a,M); build(root<<1|1,M+1,b); } } void update(int root,int a,int b,int c)//区间更新 { if(a<=tree[root].left&&tree[root].right<=b) { tree[root].acount+=c; return ; } int M=(tree[root].left+tree[root].right)>>1; if(b<=M) update(root<<1,a,b,c); else if(a>M) update(root<<1|1,a,b,c); else { update(root<<1,a,M,c); update(root<<1|1,M+1,b,c); } } int query(int root,int a)//单点访问 { int cnt=tree[root].acount; int M=(tree[root].left+tree[root].right)>>1; if(tree[root].left==tree[root].right) return cnt; if(a<=M) cnt+=query(root<<1,a); else cnt+=query(root<<1|1,a); return cnt; } int main() { int n,m,a,b,c,i; char str[10];//这里被坑了str[5] scanf("%d%d",&m,&n); build(1,1,n); for(i=1; i<=m; i++) { scanf("%s",str); if(str[0]=='A') { scanf("%d%d%d",&a,&b,&c); update(1,a,b,c); } else { scanf("%d",&a); printf("%d\n",query(1,a)); } } return 0; }
3、单点替换、区间最值
http://acm.hdu.edu.cn/showproblem.php?pid=1754
#include<iostream> #include<cstdio> #define MAXN 200000 using namespace std; struct segtree { int left,right; int ansmax; }tree[MAXN<<2]; void build(int root,int a,int b) { tree[root].left=a; tree[root].right=b; tree[root].ansmax=0; if(a<b) { int M=(tree[root].left+tree[root].right)>>1; build(root<<1,a,M); build(root<<1|1,M+1,b); } } void update(int root,int i,int e) { tree[root].ansmax=max(tree[root].ansmax,e); if(tree[root].left==tree[root].right) return ; int M=(tree[root].left+tree[root].right)>>1; if(i<=M) update(root<<1,i,e); else update(root<<1|1,i,e); } int query(int root,int a,int b) { if(tree[root].left==a&&tree[root].right==b) { return tree[root].ansmax; } int M=(tree[root].left+tree[root].right)>>1; if(b<=M) return query(root<<1,a,b); else if(a>M) return query(root<<1|1,a,b); else return max(query(root<<1,a,M),query(root<<1|1,M+1,b)); } int main() { char s; int n,m,a,b,i; while(scanf("%d%d",&n,&m)==2) { build(1,1,n); for(i=1;i<=n;i++) { scanf("%d",&a); update(1,i,a); } for(i=1;i<=m;i++) { scanf("%s%d%d",&s,&a,&b); if(s=='U') update(1,a,b); else printf("%d\n",query(1,a,b)); } } return 0; }
注:单点增减、区间最值(update使用自底向上的方式有点慢)
void update(int root,int i,int e) { if(tree[root].left==tree[root].right) { tree[root].ansmax=max(tree[root].ansmax,e); return ; } int M=(tree[root].left+tree[root].right)>>1; if(i<=M) update(root<<1,i,e); else update(root<<1|1,i,e); tree[root].ansmax=max(tree[root<<1].ansmax,tree[root<<1|1].ansmax); }
基础线段树练习:
练习一:http://acm.hdu.edu.cn/showproblem.php?pid=4339
练习二:http://210.32.0.220/onlinejudge/showProblem.do?problemCode=3635