/// General includes #include #include #include #include using namespace std; /// 单点更新合并线段树: 单点更新,区间合并 namespace MergeSegmentTree { 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