用树状数组很简单,太晚了,贴下代码睡觉去。。。
另,研究线段树的时候,发现网上流传着有几种不同的线段树,最正宗的是以单位区间为单位,只能处理线段;另外还有几种叶子结点是点的,这种也可以用来处理点,所以这题是可以用这种线段树做的。还搞不太清楚它们之间的关系。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; } } } }