【转】HDU-1166 敌兵布阵 : 熟练"建树->插数->查询“过程
#include<iostream> #include<cstdio> #include<string> using namespace std; #define Size 50000 struct node { int L, R, V; node* lchild; node* rchild; }Tree[2*Size];// 线段树 用到指针 所以整个线段树 所占空间为 2倍叶子节点-1 int Mid( node* root ) { return (root->L + root->R)/2; } int nCount; void BuildTree( node* root, int L, int R )// 初始化区间为[L,R]的线段树 { root -> L = L; root -> R = R; root -> V = 0; if( L == R ) return ; nCount++; root -> lchild = Tree + nCount; nCount++; root -> rchild = Tree + nCount; BuildTree( root->lchild, L, (L+R)/2 ); BuildTree( root->rchild, (L+R)/2+1, R ); } void Insert( node* root, int i, int v ) 在单位区间 i 上 插入 值为v的数 { if( root->L == i && root->R == i ) { root->V = v; return ; } root -> V += v;// 更新 所在路径上区间的值 if( i <= Mid( root ) ) Insert( root->lchild, i, v ); else Insert( root->rchild, i, v ); } void Add( node* root, int i, int j )// 在 i上 加上 j { if( root->L == i && root->R == i ) { root->V += j; return ; } root->V += j; if( i<=Mid( root ) ) Add( root->lchild, i, j ); else Add( root->rchild, i, j ); } int Query( node* root, int s, int e )// 区间 [s,e] 求和 { if( root->L==s && root->R == e ) return root->V; if( e<=Mid(root) ) return Query( root->lchild, s, e ); else if( s>=Mid(root)+1 ) return Query( root->rchild, s, e ); else return Query( root->lchild, s, Mid(root) ) +Query( root->rchild, Mid(root)+1, e ); } int main() { int T, N; cin>>T; for( int i=1; i<=T; i++ ) { printf( "Case %d:\n", i ); nCount = 0; scanf( "%d", &N ); BuildTree( Tree, 1, N ); int Val; for( int j=1; j<=N; j++ ) { scanf("%d", &Val); Insert( Tree, j, Val ); } string cmd; int a, b; while(cin>>cmd && cmd!="End"){ if( cmd == "Query" ) { scanf( "%d %d", &a, &b ); cout<<Query( Tree, a, b )<<endl; } else if( cmd == "Add" ) { scanf( "%d %d", &a, &b ); Add( Tree, a, b ); } else if( cmd == "Sub" ) { scanf( "%d %d", &a, &b ); Add( Tree, a, -b ); } } } return 0; }