hdu1166线段树模板求和

线段树模板,就不写其他的了

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct node
 {int l,r,sum;
 	}tr[200005];
int a[50001];
int i,j,k,m,n,t,x,y; 
int sum1;
void build(int L,int R,int num)
 {tr[num].l=L;
  tr[num].r=R;
  if(L==R)tr[num].sum=a[L];  //已到单点,赋值; 
  else
   {build(L,(L+R)/2,2*num);  //此处是向下向内部递归,注意头尾标号; 
    build((L+R)/2+1,R,2*num+1);
    tr[num].sum=tr[num*2+1].sum+tr[num*2].sum;  //注意,大区间(非单点)的值一定要在递归回来之后赋值,否则小区间或单点的值为零; 
   }
  } 
  
  
void add(int x,int y,int num)
  { tr[num].sum+=y; //所有包含点x的大区间都要变化,此处从上往下传递变化;
    if(tr[num].l==tr[num].r)return ; 
  	if(x>(tr[num].l+tr[num].r)/2)add(x,y,num*2+1);  
  	if(x<=(tr[num].l+tr[num].r)/2)add(x,y,num*2);
	}  


void query(int L,int R,int num)
 {if(tr[num].l>=L && tr[num].r<=R)
     {sum1+=tr[num].sum;
      return ;
      }
  int mid=(tr[num].l+tr[num].r)/2;
  if(mid<L)query(L,R,num*2+1);   //要找的线段在当前线段右半部;
   	 else if(mid>=R)query(L,R,num*2);  //要找的线段在当前线段左半部;
		else       //要找的线段一部分在左,一部分在右,两边都找; 
		  {query(L,R,num*2+1);
		   query(L,R,num*2);	
		   } 
 }
	
int main()
 {scanf("%d",&t);
  k=t;
  while(t--)
   {scanf("%d",&n);
    printf("Case %d:\n",k-t);
   	for(i=1;i<=n;i++)scanf("%d",&a[i]);
    build(1,n,1);
    char str[5];
	while(~scanf("%s",&str))
	  {if(str[0]=='E')break;
	   scanf("%d%d",&x,&y);
	   sum1=0;
	   if(str[0]=='A')add(x,y,1);
	   if(str[0]=='S')add(x,-y,1);
	   if(str[0]=='Q')
	     {query(x,y,1);
	      printf("%d\n",sum1);
		  }
       }
   }
 return 0;	
  } 


你可能感兴趣的:(线段树,ACM)