Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 43219 Accepted Submission(s): 18304
1 10 1 2 3 4 5 6 7 8 9 10 Query 1 3 Add 3 6 Query 2 7 Sub 10 2 Add 6 3 Query 3 10 End
Case 1: 6 33 59
题目大意:
给你编号为1-N的区间,包含N个节点,每个节点上有值,然后根据输入进行4条命令:
(1)在第i个点上增加值为j的数;(2)在第i个点上减少值为j的数;(3)询问第i个点到第j个点
的总和(4)输入END结束命令
思路:建立1-N的线段树,进行单点更新,然后区间求和
线段树功能:update:单点增减 query:区间求和
很早之前写的线段树:
# include<stdio.h> # include<string.h> # define MAX 150500 struct segmenttree { int a; int b; int count; }tree[MAX]; int ren[50500],SUM; void find(int i,int a,int b) { if(a<=tree[i].a && b>=tree[i].b) SUM += tree[i].count; else { int m = (tree[i].a + tree[i].b)/2; if(b <= m) find(2*i,a,b); else if(a > m) find(2*i+1,a,b); else { find(2*i,a,m); find(2*i+1,m,b); } } } void init(int i,int a,int b) { tree[i].a = a; tree[i].b = b; if(a == b) tree[i].count = ren[b]; else { int m = (a+b)/2; init(2*i,a,m); init(2*i+1,m+1,b); tree[i].count = tree[2*i].count + tree[2*i+1].count; } } void add(int i,int a,int b) { tree[i].count += b; if(tree[i].a==a && tree[i].b==a) return; int m = (tree[i].a + tree[i].b) /2; if(a>m) add(2*i+1,a,b); else add(2*i,a,b); } void sub(int i,int a,int b) { tree[i].count -= b; if(tree[i].a==a && tree[i].b==a) return; int m = (tree[i].a + tree[i].b) /2; if(a>m) sub(2*i+1,a,b); else sub(2*i,a,b); } int main() { int T,N,i,j,a,b; char operate[10]; scanf("%d",&T); j = 1; while(T--) { scanf("%d",&N); memset(ren,0,sizeof(ren)); ren[0] = 0; for(i=1;i<=N;i++) scanf("%d",&ren[i]); init(1,1,N); printf("Case %d:\n",j++); getchar(); while(scanf("%s",operate) && strcmp(operate,"End")!=0) { if(strcmp(operate,"Query")==0) { scanf("%d %d",&a,&b); SUM = 0; find(1,a,b); printf("%d\n",SUM); } else if(strcmp(operate,"Add")==0) { scanf("%d %d",&a,&b); add(1,a,b); } else if(strcmp(operate,"Sub")==0) { scanf("%d %d",&a,&b); sub(1,a,b); } } } return 0; }
系统学习时写的线段树
# include<stdio.h> # include<iostream> # include<algorithm> using namespace std; const int INF = 0xffffff0; const int MAXN = 50010; int sum[MAXN<<2]; void pushup(int root) { sum[root] = sum[root<<1] + sum[root<<1|1]; } void build(int root,int L,int R) { if(L == R) { scanf("%d",&sum[root]); return; } int mid = (L+R)>>1; build(root<<1,L,mid); build(root<<1|1,mid+1,R); pushup(root); } void update(int root,int L,int R,int i,int v) { if(L==R) { sum[root] += v; return ; } int mid = (L+R)>>1; if(i <= mid) update(root<<1,L,mid,i,v); else update(root<<1|1,mid+1,R,i,v); pushup(root); } int query(int root,int L,int R,int s,int e) { if(s==L && e==R) return sum[root]; int mid = (L+R)>>1; int res = 0; if(e <= mid) res += query(root<<1,L,mid,s,e); else if(s > mid) res += query(root<<1|1,mid+1,R,s,e); else { res += query(root<<1,L,mid,s,mid); res += query(root<<1|1,mid+1,R,mid+1,e); } return res; } int main() { int T, N, a, b, kase = 1; char cmp[10]; scanf("%d", &T); while(T--) { printf("Case %d:\n",kase++); scanf("%d",&N); build(1,1,N); while(scanf("%s",cmp) && cmp[0]!='E') { scanf("%d%d",&a, &b); if(cmp[0]=='Q') printf("%d\n",query(1,1,N,a,b)); else if(cmp[0]=='A') update(1,1,N,a,b); else if(cmp[0]=='S') update(1,1,N,a,-b); } } return 0; }