题目大意:
给你一个长度为n的序列,然后,有下列操作:
Q:查询[x,y]区间的和.
A: 给a[x]+y
S: 给a[x]-y
E: 结束查询
解题思路:
由于n很大,询问的次数也很大,最坏的情况就是,每当我进行一次A或者S,我又进行一次Q,这样的复杂度是N*M,,,肯定会T,那我们就需要在logn的时间内来解决查询和修改的问题,想当然是使用树状数组了,裸裸的树状数组的模板题。
代码:
# include<cstdio> # include<iostream> # include<fstream> # include<algorithm> # include<functional> # include<cstring> # include<string> # include<cstdlib> # include<iomanip> # include<numeric> # include<cctype> # include<cmath> # include<ctime> # include<queue> # include<stack> # include<list> # include<set> # include<map> using namespace std; const double PI=4.0*atan(1.0); typedef long long LL; typedef unsigned long long ULL; # define inf 999999999 # define MAX 50000+4 int a[MAX]; int tree[MAX]; char ss[23]; int n; int read ( int pos ) { int ans = 0; while ( pos > 0 ) { ans+=tree[pos]; pos-=pos&(-pos); } return ans; } void update( int pos,int val ) { while ( pos <= n ) { tree[pos]+=val; pos+=pos&(-pos); } } void init() { for ( int i = 1;i <= n;i++ ) { update(i,a[i]); } } int main(void) { int icase = 1; int t;scanf("%d",&t); while ( t-- ) { memset(a,0,sizeof(a)); memset(tree,0,sizeof(tree)); scanf("%d",&n); for ( int i = 1;i <= n;i++ ) { scanf("%d",&a[i]); } //getchar(); init(); printf("Case %d:\n",icase++); while ( scanf("%s",ss) ) { if ( ss[0] == ‘E‘ ) break; int x, y;scanf("%d %d",&x,&y); if ( ss[0] == ‘Q‘ ) { int ans1 = read(x-1); int ans2 = read(y); cout<<ans2-ans1<<endl; } else if ( ss[0] == ‘A‘ ) { update(x,y); } else if ( ss[0] == ‘S‘ ) { update(x,(-1)*y); } } } return 0; }
原文:http://www.cnblogs.com/wikioibai/p/4397227.html