用树状数组很简单,太晚了,贴下代码睡觉去。。。
另,研究线段树的时候,发现网上流传着有几种不同的线段树,最正宗的是以单位区间为单位,只能处理线段;另外还有几种叶子结点是点的,这种也可以用来处理点,所以这题是可以用这种线段树做的。还搞不太清楚它们之间的关系。mark一下,明天再说。。。
代码
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
inline int Rint() {int x; scanf("%d", &x); return x;}
#define FF(x1, x2) for(int i=x1; i<x2; i++)
#define LOWBIT(x) x&(-x)
#define MAXN 50002 //点数
int c[MAXN];
int getSum(int x)
{
int sum=0;
while(x>0)
{
sum+=c[x];
x-=LOWBIT(x);
}
return sum;
}
void add(int i, int j)
{
while(i<MAXN)
{
c[i]+=j;
i+=LOWBIT(i);
}
}
void sub(int i, int j)
{
while(i<MAXN)
{
c[i]-=j;
i+=LOWBIT(i);
}
}
int query(int i, int j)
{
return getSum(j)-getSum(i-1); //i-1
}
void clear() {memset(c, 0, sizeof(c));}
int main()
{
int t = Rint();
FF(1, t+1)
{
clear(); //① 清空树状数组
printf("Case %d:\n", i);
int n = Rint();
FF(1, n+1) //正整数N、正整数ai
{
int j = Rint();
add(i, j);
}
char opt[10];
while(scanf("%s", opt) && opt[0]!='E')
{
int i=Rint(); int j=Rint();
switch(opt[0])
{
case 'Q': printf("%d\n", query(i, j)); break;
case 'A': add(i, j); break;
case 'S': sub(i, j); break;
}
}
}
}