poj3468_線段樹

題目描述:

   標準的線段樹。給出序列操作,分別爲對一段區間增值 和 求某一段區間和。

 

解題思路:

   標準的線段樹建樹,修改和查詢操作。這裏要注意的是,對修改操作爲了避免修改到葉子節點而導致的超時問題,令修改到對應的區間即可,而此時爲了保證該區間下的節點能夠意識到自己的值已經被修改了——通過對該區間打延時標記來實現。

  附註:有個坑,就是增量得開到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 right area
              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;
   }else if(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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章