题目链接:点击打开链接
题目大意:
多组数据,单点更新,区间查询
思路:
裸的线段树,手打了一遍练练感觉,但是问题还是挺多的;
总结一下,
(1)单点更新时,以mid作为基准,如果mid>=id查左边的,如果mid<id查右边的;
(2)build的时候,要理清思路,先给树的左右节点位置赋值;
(3)查询时,应该以当前树的L和R算出mid,设查询区间为(l,r),如果l<=mid,则查询左子树,否则查右子树,最后一步才返回ans;
(4)在单点更新时,终止条件是 l==r !!!!!!!!!
(5)当读到End的时候,是没有输入的!!!这一点卡了很久!!!
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <cmath>
using namespace std;
#define INIT(x) memset(x,0,sizeof(x))
#define eps 1e-8
#define next next_
typedef long long ll;
typedef unsigned long long ull;
const ll INF = 0x7fffffff;
const ll inf = 0x3f3f3f3f;
const ll maxn = 100005;
const ll N = 105;
inline void read(ll &x) {
ll f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
ll T,n,a[maxn];
struct node{
ll l,r,sum;
}t[maxn*4];
string s;
void build(ll x,ll l,ll r) {
t[x].l =l, t[x].r = r, t[x].sum = 0;
if(l==r) {t[x].sum = a[l]; return;}
ll mid = (l+r) / 2;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
t[x].sum = t[x<<1].sum + t[x<<1|1].sum;
}
void add(ll x,ll p,ll y) {
ll l = t[x].l, r = t[x].r;
if(l==r) { //重点,不是l==p!!!!!!!!!!!!
t[x].sum += y;
return;
}
ll mid = (l+r) / 2;
if(p<=mid) add(x<<1,p,y);
else add(x<<1|1,p,y);
t[x].sum = t[x<<1].sum + t[x<<1|1].sum;
}
ll query(ll x,ll p,ll y) { //p左y右
ll res = 0;
ll l = t[x].l, r = t[x].r;
if(p<=l && y>=r) {return t[x].sum;}
ll mid = (l+r) / 2;
if(p<=mid) res += query(x<<1,p,y);
if(y>mid) res += query(x<<1|1,p,y);
return res;
}
int main() {
cin>>T;
ll idx = 1;
while(T--) {
cout<<"Case "<<idx++<<":"<<endl;
read(n);
for(ll i=1;i<=n;i++) read(a[i]);
build(1,1,n);
while(cin>>s) {
ll p,y;
if(s=="End") break;
read(p), read(y);
if(s=="Add") {
add(1,p,y);
}
else if(s=="Sub") {
add(1,p,-y);
}
else if(s=="Query"){
cout<<query(1,p,y)<<endl;
}
}
}
return 0;
}