From de7a05cdffa725a171222e497dda5a45837eec18 Mon Sep 17 00:00:00 2001 From: Kirito <1362050620@qq.com> Date: Fri, 19 Aug 2016 16:45:32 +0800 Subject: [PATCH] Update Segment-tree.cpp LCIS & Segment Tree added. --- .ACM-Templates/Segment-tree.cpp | 156 ++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/.ACM-Templates/Segment-tree.cpp b/.ACM-Templates/Segment-tree.cpp index 8e7e0b4..9f03e5f 100644 --- a/.ACM-Templates/Segment-tree.cpp +++ b/.ACM-Templates/Segment-tree.cpp @@ -384,3 +384,159 @@ int query(int Val,int _indexer=1) } }/// End of namespace AttributeMergeSegmentTree + + + + +/// 最长连续上升字串 与线段树结合 (LCIS & Segment Tree) +namespace LCISSegmentTree +{ + +const int MAXN = 1000100; +const int MAXTREENODE = MAXN<<2; + + +int seq[MAXN]; + +struct node +{ + /// Be Sure That "BounderLen" always equal to "RightBounder - LeftBounder + 1" + /// And Bounder Never change in one single test. + int leftbounder,rightbounder,bounderlen; + int leftseqlen,rightseqlen,mergedseqlen; /// From HDU 3308 + int leftvalue,rightvalue; +}; + +node tree[MAXTREENODE]; + +/// _internal_v is a indexer of SegmentTree. It guides the procedure to the right node. + +void pushup(int _internal_v) +{ + /// Left == Left.Left + tree[_internal_v].leftseqlen=tree[_internal_v<<1].leftseqlen; + tree[_internal_v].leftvalue=tree[_internal_v<<1].leftvalue; + + /// Right == Right.Right + tree[_internal_v].rightseqlen=tree[_internal_v<<1|1].rightseqlen; + tree[_internal_v].rightvalue=tree[_internal_v<<1|1].rightvalue; + + /// Merged SeqLen is the max one of two sub-tree.MergedSeqLen + tree[_internal_v].mergedseqlen=max(tree[_internal_v<<1].mergedseqlen,tree[_internal_v<<1|1].mergedseqlen); + + /// If LeftSon.RightValue < RightSon.LeftValue, a longer Seq may exist. + if(tree[_internal_v<<1].rightvalue>1; + build(L,mid,_internal_v<<1); + build(mid+1,R,_internal_v<<1|1);/// x<<1 == x*2; x<<1|1 == x*2+1; (faster == slower) + + /// Push Up + pushup(_internal_v); +} + +void update(int Pos,int Val,int _internal_v=1)/// Update a position, _internal_v is 1 by default. +{ + /// Reach a clearly node with same LeftBounder and RightBounder + if(tree[_internal_v].leftbounder==tree[_internal_v].rightbounder) + { + tree[_internal_v].leftvalue=tree[_internal_v].rightvalue=Val; + return; + } + /// Calculate Mid + int mid=(tree[_internal_v].leftbounder+tree[_internal_v].rightbounder)>>1; + /// If in left then try update in left + if(Pos <= mid) + update(Pos,Val,_internal_v<<1); + else /// Else try update in right + update(Pos,Val,_internal_v<<1|1); + /// And then push it up ! + pushup(_internal_v); +} + +int query(int L,int R,int _internal_v=1) +{ + /// This Node ( and the segment which is under its control ) + /// is included in query area. + if(L<=tree[_internal_v].leftbounder && tree[_internal_v].rightbounder <= R) + { + return tree[_internal_v].mergedseqlen; + } + /// Calculate Mid + int mid=(tree[_internal_v].leftbounder+tree[_internal_v].rightbounder)>>1; + /// Answer saved in 'ans' + int ans=0; + + /// Query If Segment L~R has common area with ThisNode.LeftBounder~Mid + if(L<=mid) + { + ans=max(ans,query(L,R,_internal_v<<1)); + } + + /// Query If Segment L~R has common area with Mid+1 ~ ThisNode.RightBounder + if(mid