poj3468_线段树

来源:互联网 发布:安尼威尔监控app软件 编辑:程序博客网 时间:2024/05/16 08:52

题目描述:

   标准的线段树。给出序列操作,分别为对一段区间增值 和求某一段区间和。

 

解题思路:

  标准的线段树建树,修改和查询操作。这里要注意的是,对修改操作为了避免修改到叶子节点而导致的超时问题,令修改到对应的区间即可,而此时为了保证该区间下的节点能够意识到自己的值已经被修改了——通过对该区间打延时标记来实现。

  附注:有个坑,就是增量得开到64位long long。

 

代码:

#include
#include
#define N 100001

typedef struct{
   int left, right;
   long long tab;
   long long inc;//标记
}CH;

CH segTree[4*N];
int n,q, num[N];
long long sum;


void buildTree(int l, int r, int index){
   segTree[index].left = l;
   segTree[index].right =r;
   segTree[index].tab = 0;
   segTree[index].inc = 0;
   if(l!=r){
     buildTree(l,(l+r)/2,2*index);
     buildTree((l+r)/2+1,r,2*index+1);
   }
}

void changeTree(int l, int r, int t, int index){
   if(segTree[index].left <= l&& segTree[index].right >= r){
      //printf("更改区域[%d-%d],增加值%d\n",segTree[index].left,segTree[index].right,(r-l+1)*t);
      segTree[index].tab += (r-l+1)*t;
      
      if(!(segTree[index].left == l && segTree[index].right ==r)){ //不是恰好符合的区间,继续更新
          if(l>(segTree[index].left+segTree[index].right)/2){ // in rightarea
             changeTree(l,r,t,2*index+1);
          }else if(r <=(segTree[index].left+segTree[index].right)/2){
             changeTree(l,r,t,2*index);
          }else{
             changeTree(l,(segTree[index].left+segTree[index].right)/2,t,2*index);
             changeTree((segTree[index].left+segTree[index].right)/2+1,r,t,2*index+1);
          }
      }else{ //恰好符合的区间,添加标记
         //printf("在区域[%d-%d]添加inc=%d\n",segTree[index].left,segTree[index].right,(r-l+1)*t);
          segTree[index].inc += t;
          
           
   }
}

void searchTree(int l, int r, int index){
  
   if(l == segTree[index].left&& r == segTree[index].right){
     //printf("在[%d-%d]区域,添加tab=%d\n",l,r,segTree[index].tab);
     sum += segTree[index].tab;
   }elseif(l>(segTree[index].left+segTree[index].right)/2){
    //printf("在[%d-%d]区域,添加inc=%d\n",segTree[index].left,segTree[index].right,segTree[index].inc*(r-l+1));
     sum += segTree[index].inc*(r-l+1);
     searchTree(l,r,2*index+1);
   }else if(r <=(segTree[index].left+segTree[index].right)/2){
    //printf("在[%d-%d]区域,添加inc=%d\n",segTree[index].left,segTree[index].right,segTree[index].inc*(r-l+1));
     sum += segTree[index].inc*(r-l+1);
     searchTree(l,r,2*index);
   }else{
    //printf("在[%d-%d]区域,添加inc=%d\n",segTree[index].left,segTree[index].right,segTree[index].inc*(r-l+1));
     sum += segTree[index].inc*(r-l+1);
     searchTree(l,(segTree[index].left+segTree[index].right)/2,2*index);
     searchTree((segTree[index].left+segTree[index].right)/2+1,r,2*index+1);
   }
}

main(){
   char order[2];
   int l, r, c, i;
  
   scanf("%d%d",&n,&q);
   buildTree(1,n,1);
   for(i=1;i<=n;i++){
     scanf("%d",&num[i]);
     changeTree(i,i,num[i],1);
   }
  
  //printf("----------------------------------\n\n");
   for(i=1;i<=q;i++){
     scanf("%s",order);
     if(strcmp(order,"Q")==0){
        sum = 0;
        scanf("%d %d",&l, &r);
        searchTree(l,r,1);
        printf("%lld\n",sum);
     }else{
        scanf("%d %d %d",&l,&r,&c);
        changeTree(l,r,c,1);
     }
   }

   system("pause");
   return 0;
}