ACM集训--HDU 1166

来源:互联网 发布:ubuntu 覆盖安装 编辑:程序博客网 时间:2024/05/17 23:24

线段树模板题:

     hdu1166,先摆模板:


    

(1):线段树的构造 void build(int l, int r, int rt);

主要思想是递归构造,如果当前节点记录的区间只有一个值,则直接赋值,否则递归构造左右子树,最后回溯的时候给当前节点赋值

<span style="font-family:Comic Sans MS;">void Build(int l, int r, int rt)  {      if(l == r)      {          scanf("%d", &sum[rt]);          return ;      }      int m = ( l + r )>>1;        Build(lson);      Build(rson);      PushPlus(rt);  }</span>


(2):区间查询int query(int node, int begin, int end, int left, int right);

(其中node为当前查询节点,begin,end为当前节点存储的区间,left,right为此次query所要查询的区间)

主要思想是把所要查询的区间[a,b]划分为线段树上的节点,然后将这些节点代表的区间合并起来得到所需信息

<span style="font-family:Comic Sans MS;">int query(int node, int begin, int end, int left, int right)    {       int p1, p2;            /*  查询区间和要求的区间没有交集  */      if (left > end || right < begin)            return -1;            /*  if the current interval is included in  */        /*  the query interval return segTree[node]  */      if (begin >= left && end <= right)            return segTree[node];            /*  compute the minimum position in the  */      /*  left and right part of the interval  */       p1 = query(2 * node, begin, (begin + end) / 2, left, right);       p2 = query(2 * node + 1, (begin + end) / 2 + 1, end, left, right);            /*  return the expect value  */       if (p1 == -1)            return p2;        if (p2 == -1)            return p1;        if (p1 <= p2)            return  p1;        return  p2;      }   </span><span style="font-family:FangSong_GB2312;"></span>

a:单节点更新

<span style="font-family:Comic Sans MS;">void Updata(int node, int begin, int end, int ind, int add)/*单节点更新*/    {            if( begin == end )        {            segTree[node] += add;            return ;        }        int m = ( left + right ) >> 1;        if(ind <= m)            Updata(node * 2,left, m, ind, add);        else            Updata(node * 2 + 1, m + 1, right, ind, add);        /*回溯更新父节点*/        segTree[node] = min(segTree[node * 2], segTree[node * 2 + 1]);              }  </span><span style="font-family: FangSong_GB2312; "> </span>
HDU1166用的就是单节点更新

<span style="font-family:Comic Sans MS;">#include<cstring>   #include<iostream>     #define M 50005   #define lson l,m,rt<<1   #define rson m+1,r,rt<<1|1   /*left,right,root,middle*/    int sum[M<<2];    inline void PushPlus(int rt)  {      sum[rt] = sum[rt<<1] + sum[rt<<1|1];  }    void Build(int l, int r, int rt)  {      if(l == r)      {          scanf("%d", &sum[rt]);          return ;      }      int m = ( l + r )>>1;        Build(lson);      Build(rson);      PushPlus(rt);  }    void Updata(int p, int add, int l, int r, int rt)  {        if( l == r )      {          sum[rt] += add;          return ;      }      int m = ( l + r ) >> 1;      if(p <= m)          Updata(p, add, lson);      else          Updata(p, add, rson);        PushPlus(rt);  }    int Query(int L,int R,int l,int r,int rt)  {      if( L <= l && r <= R )      {          return sum[rt];      }      int m = ( l + r ) >> 1;      int ans=0;      if(L<=m )          ans+=Query(L,R,lson);      if(R>m)          ans+=Query(L,R,rson);        return ans;  }  int main()  {         int T, n, a, b;      scanf("%d",&T);      for( int i = 1; i <= T; ++i )      {          printf("Case %d:\n",i);          scanf("%d",&n);          Build(1,n,1);            char op[10];            while( scanf("%s",op) &&op[0]!='E' )          {                scanf("%d %d", &a, &b);              if(op[0] == 'Q')                  printf("%d\n",Query(a,b,1,n,1));              else if(op[0] == 'S')                  Updata(a,-b,1,n,1);              else                  Updata(a,b,1,n,1);            }      }      return 0;  }  </span>

要学会使用模板,必须好好的理解算法,至少要明确每个变量的意义,思路清晰了,代码也就不是问题
  参考http://blog.csdn.net/metalseed/article/details/8039326



0 0