1. 程式人生 > >1166 敵兵佈陣(線段樹)

1166 敵兵佈陣(線段樹)

解析:線段樹的單點更新,線段樹套用線段樹的模板。、

#include <cstdio>
#include <cstring>
using namespace std;
const int N = 50005;
int s[N << 2], L[N << 2], R[N << 2];
int a[N];
void build(int u,int l,int r) {
	if(l == r) {
		R[u] = L[u] = l;
		s[u] = a[l];
		return ;
	}
	int mid = (l + r) / 2;
	build(u*2,l,mid);
	build(u*2+1,mid+1,r);
	L[u] = l;
	R[u] = r;
	s[u] = s[u*2] + s[u*2+1];
}
void modify(int u,int x,int v) {
	if(R[u] == x && L[u] == x) { //葉子節點
		s[u] = s[u] + v;
		return ;
	}
	//非葉子節點
	int mid = (L[u] + R[u]) / 2;
	if(x <= mid) {
		modify(u*2,x,v);
	}else {
		modify(u*2+1,x,v);
	}
	s[u] = s[u] + v;
}
int query(int u,int l,int r) {
	if(l <= L[u] && R[u] <= r) {
		return s[u];
	}
	int mid = (L[u] + R[u]) / 2;
	if(r <= mid) { //如果左區間有涉及
		return query(u*2,l,r); //則遞迴左邊子樹
	}else if(l > mid) { //如果右區間有涉及
		return query(u*2+1,l,r); //則遞迴右字數
	}else { //如果都沒有涉及
		return query(u*2,l,r) + query(u*2+1,l,r);
	}
}
int main() {
	int T,n,cas = 1;
	int l,r;
	int x,v;
	scanf("%d",&T);
	while(T--) {
		scanf("%d",&n);
		for(int i = 1; i <= n; i++) {
			scanf("%d",&a[i]);	
		}
		memset(s,0,sizeof(s));
		L[1] = 1;
		R[1] = n;
		build(1,L[1],R[1]);
		char cmd[20];
		printf("Case %d:\n",cas++);
		while(scanf("%s",cmd) != EOF) {
			if(cmd[0] == 'Q') {
				scanf("%d%d",&l,&r);
				printf("%d\n",query(1,l,r));
			}else if(cmd[0] == 'A') {
				scanf("%d%d",&x,&v);
				modify(1,x,v);
			}else if(cmd[0] == 'S') {
				scanf("%d%d",&x,&v);
				modify(1,x, -v);
			}else if(cmd[0] == 'E') {
				break;
			}
		}
	}
	return 0;
}