SegmentTree

 SegmentTree:适用于区间插入,区间查找最值。 

 

#include <iostream>
#include <stdio.h>
#include <algorithm>

using namespace std;

struct node
{
 int left, right;
 int pos;
 int mweight;
 int r;
 node *lchild, *rchild;
 node() {
  lchild = rchild = NULL;
  pos = 0;          // pos: mweight
  mweight = 0;
  r = 0;
 }
};

class hpSegmentTree
{
private:
 node *root;
 int nodecnt;
 
public:
 hpSegmentTree(){
  root = NULL;
  nodecnt = 0;
 }
 ~hpSegmentTree(){
  Clear();
 } 
 void Clear();
 int NodeCount();
 void BuildSegmentTree( int, int );
 void AddInterval( int, int, int );
 int GetMaxInInterval( int, int, int* );

private:
 void __clear( node *);
 void __build( node *, int, int );
 void __addInterval( node *, int, int, int );
 int __getMaxInInterval( node *, int, int, int* );
 void __update( node *);
};

///
void hpSegmentTree::Clear()
{
 nodecnt = 0;
 if ( root != NULL )
 {
  __clear( root->lchild );
  __clear( root->rchild );
  delete root;
  root = NULL;
 }
}
void hpSegmentTree::BuildSegmentTree( int left, int right )
{
 root = new node();
 nodecnt = 1;
 __build( root, left, right );
}
int hpSegmentTree::NodeCount() { return nodecnt; }

void hpSegmentTree::AddInterval( int left, int right, int value )
{
 __addInterval( root, left, right, value );
}
int hpSegmentTree::GetMaxInInterval( int left, int right, int *ret)
{
 return __getMaxInInterval( root, left, right, ret );
}

/
void hpSegmentTree::__clear( node *p )
{
 if ( p != NULL )
 {
  __clear( p->lchild );
  __clear( p->rchild );
  delete p;
 }
}

void hpSegmentTree::__build( node *p, int left, int right )
{
 p->left = left; 
 p->right = right;
 p->pos = p->left;

 if ( right > left )
 {
  int mid = (left+right)>>1;
  p->lchild = new node();
  p->rchild = new node();
  nodecnt += 2;
  __build( p->lchild, left, mid );
  __build( p->rchild, mid+1, right );
 }
}
void hpSegmentTree::__addInterval( node *p, int left, int right, int value )
{
 int mid = (p->left+p->right)>>1;
 int r = p->r;

 if ( left <= p->left && right >= p->right )
 {
  p->mweight += value;
  p->r += value;
        /*
  //往下更新,其实这里在节点设置一个变量,下次查询时顺带更新!    
  if ( p->lchild != NULL )
  {
   __addInterval( p->lchild, p->left, mid, value );
   __addInterval( p->rchild, mid+1, p->right, value );
  }
  */
  return;
 }
 
 p->lchild->mweight += r;
 p->lchild->r += r;
 p->rchild->mweight += r;
 p->rchild->r += r;
 p->r = 0;

 if ( left <= mid )
  __addInterval( p->lchild, left, right, value );
 if ( right > mid )
  __addInterval( p->rchild, left, right, value );

 if ( p->lchild->mweight >= p->rchild->mweight )
 {
  p->mweight = p->lchild->mweight;
  p->pos = p->lchild->pos;
 }
 else {
  p->mweight = p->rchild->mweight;
  p->pos = p->rchild->pos;
 }
}
int hpSegmentTree::__getMaxInInterval( node *p, int left, int right, int *ret )
{
 int mid = (p->left+p->right)>>1;
 int r = p->r;

 if ( left <= p->left && right >= p->right )
 {
  *ret = p->pos;
  return p->mweight;
 }

 p->lchild->mweight += r;
 p->lchild->r += r;
 p->rchild->mweight += r;
 p->rchild->r += r;
 p->r = 0;

 if ( left <= mid && right > mid )
 {
  int l, lp, rp;

  l = __getMaxInInterval( p->lchild, (left>p->left)?left:p->left, mid, &lp );
  r = __getMaxInInterval( p->rchild, mid+1, (right<p->right)?right:p->right, &rp );
  if ( l >= r )
  {
   *ret = lp;
   return l;
  }
  else {
   *ret = rp;
   return r;
  }
 }
 else if ( right <= mid )
 {
  return __getMaxInInterval( p->lchild, (left>p->left)?left:p->left, right, ret );
 } 
 else if ( left > mid )
 {
  return __getMaxInInterval( p->rchild, left, (right<p->right)?right:p->right, ret );
 }
}
void hpSegmentTree::__update( node *p )
{
 if ( p->lchild != NULL )
 {
  p->lchild->mweight = p->mweight;
  __update( p->lchild );
 }
 if ( p->rchild != NULL )
 {
  p->rchild->mweight = p->mweight;
  __update( p->rchild );
 }
}

int main( int argc, char *argv[] )
{
 int n, m, i, a, b, c, pos, result;
 char ch;
 hpSegmentTree tree;
 while ( scanf("%d%d", &n, &m) != EOF && n && m )
 {
  tree.BuildSegmentTree( 1, n );
  result = 0;
  for ( i = 0; i < m; ++ i )
  {
   scanf(" %c%d%d", &ch, &a, &b);
   if ( ch == 'I' )
   {
    scanf("%d", &c);
    tree.AddInterval( a, b, c );
   }
   else {
    result = tree.GetMaxInInterval( a, b, &pos );
    tree.AddInterval( pos, pos, -result );
    printf("%d\n", result );
   }
  } 
  tree.Clear();
 }
 tree.Clear();
 return 0;
}

 

用这段代码过了Sicily 1686,没有加红色代码,就会超时,由此可见它的重要性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值