线段树模板

摘抄自http://www.notonlysuccess.com/index.php/segment-tree-complete/

  • maxn是题目给的最大区间,而节点数要开4倍,确切的来说节点数要开大于maxn的最小2x的两倍
  • lson和rson分辨表示结点的左儿子和右儿子,由于每次传参数的时候都固定是这几个变量,所以可以用预定于比较方便的表示
  • 以前的写法是另外开两个个数组记录每个结点所表示的区间,其实这个区间不必保存,一边算一边传下去就行,只需要写函数的时候多两个参数,结合lson和rson的预定义可以很方便
  • PushUP(int rt)是把当前结点的信息更新到父结点
  • PushDown(int rt)是把当前结点的信息更新给儿子结点
  • rt表示当前子树的根(root),也就是当前所在的结点
  • #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
     
    const int maxn = 55555;
    int lsum[maxn<<2] , rsum[maxn<<2] , msum[maxn<<2];
    int cover[maxn<<2];
     
    void PushDown(int rt,int m) {
        if (cover[rt] != -1) {
            cover[rt<<1] = cover[rt<<1|1] = cover[rt];
            msum[rt<<1] = lsum[rt<<1] = rsum[rt<<1] = cover[rt] ? 0 : m - (m >> 1);
            msum[rt<<1|1] = lsum[rt<<1|1] = rsum[rt<<1|1] = cover[rt] ? 0 : (m >> 1);
            cover[rt] = -1;
        }
    }
    void PushUp(int rt,int m) {
        lsum[rt] = lsum[rt<<1];
        rsum[rt] = rsum[rt<<1|1];
        if (lsum[rt] == m - (m >> 1)) lsum[rt] += lsum[rt<<1|1];
        if (rsum[rt] == (m >> 1)) rsum[rt] += rsum[rt<<1];
        msum[rt] = max(lsum[rt<<1|1] + rsum[rt<<1] , max(msum[rt<<1] , msum[rt<<1|1]));
    }
    void build(int l,int r,int rt) {
        msum[rt] = lsum[rt] = rsum[rt] = r - l + 1;
        cover[rt] = -1;
        if (l == r) return ;
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
    }
    void update(int L,int R,int c,int l,int r,int rt) {
        if (L <= l && r <= R) {
            msum[rt] = lsum[rt] = rsum[rt] = c ? 0 : r - l + 1;
            cover[rt] = c;
            return ;
        }
        PushDown(rt , r - l + 1);
        int m = (l + r) >> 1;
        if (L <= m) update(L , R , c , lson);
        if (m < R) update(L , R , c , rson);
        PushUp(rt , r - l + 1);
    }
    int query(int w,int l,int r,int rt) {
        if (l == r) return l;
        PushDown(rt , r - l + 1);
        int m = (l + r) >> 1;
        if (msum[rt<<1] >= w) return query(w , lson);
        else if (rsum[rt<<1] + lsum[rt<<1|1] >= w) return m - rsum[rt<<1] + 1;
        return query(w , rson);
    }

     

posted @ 2013-06-01 16:42  小仪在努力~  阅读(159)  评论(0编辑  收藏  举报