1166 敵兵佈陣(線段樹)
阿新 • • 發佈:2019-02-08
解析:線段樹的單點更新,線段樹套用線段樹的模板。、
#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; }