敌兵布阵 HDU 1166 线段树
题意
这个题是用中文来描写的,很简单,没什么弯。
解题思路
这个题肯定就是用线段树来做了,不过当时想了一下可不可用差分来做,因为不熟练就还是用了线段树来做,几乎就是模板题了。
代码实现
#include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<iostream> # define ls (rt<<1) # define rs (rt<<1|1) using namespace std; const int maxn=5e4+7; struct node{ int l, r; int sum, lazy; }t[maxn<<2]; int num[maxn]; int n, m; void up(int rt) { t[rt].sum=t[ls].sum+t[rs].sum; } void build(int rt, int l, int r) { t[rt].l=l; t[rt].r=r; t[rt].lazy=0; if(l==r) { t[rt].sum=num[l]; return ; } int mid=(l+r)>>1; build(ls, l, mid); build(rs, mid+1, r); up(rt); } void down(int rt) { if(t[rt].lazy!=0) { t[ls].lazy+=t[rt].lazy; t[ls].sum+=t[rt].lazy; t[rs].lazy+=t[rt].lazy; t[rs].sum+=t[rt].lazy; t[rt].lazy=0; } } void update(int rt, int x, int v) { if(t[rt].l == t[rt].r ) { t[rt].lazy+=v; t[rt].sum+=v; return ; } down(rt); int mid=(t[rt].l+t[rt].r)>>1; if(x<=mid) update(ls, x, v); else update(rs, x, v); up(rt); } int query(int rt, int l, int r) { if(l <= t[rt].l && t[rt].r <= r) { return t[rt].sum; } down(rt); int ans=0; int mid=(t[rt].l+t[rt].r)>>1; if(l<=mid) ans+=query(ls, l, r); if(r>mid) ans+=query(rs, l, r); return ans; } int main() { int t; scanf("%d", &t); for(int ca=1; ca<=t; ca++) { scanf("%d", &n); for(int i=1; i<=n; i++) { scanf("%d", &num[i]); } build(1, 1, n); string op; int x, y; printf("Case %d:\n", ca); while(cin >> op && op!="End") { scanf("%d%d", &x, &y); if(op=="Query") { printf("%d\n", query(1, x, y)); } else if(op=="Add") { update(1, x, y); } else update(1, x, -y); } } return 0; }