生活随笔
收集整理的這篇文章主要介紹了
2021牛客暑期多校训练营7 B-xay loves monotonicity(线段树+不降子序列)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
P4198 樓房重建
線段樹維護(hù)以某點(diǎn)為開頭的最長(zhǎng)不下降子序列
使用下面calc函數(shù)能夠計(jì)算線段樹u維護(hù)的區(qū)間中,以x為開頭最長(zhǎng)不下降子序列的個(gè)數(shù)。
calc需要維護(hù)區(qū)間最值。
template<typename T>
int calc(int u
,T x
)
{if(tree
[u
].l
==tree
[u
].r
) return tree
[u
].v
>x
?1:0;if(tree
[u
<<1].v
<=x
) return calc(u
<<1|1,x
);return tree
[u
].cnt
-tree
[u
<<1].cnt
+calc(u
<<1,x
);
}
B-xay loves monotonicity
如果本題沒有b數(shù)組,就是上面的樓房重建,用上面calc函數(shù)遞歸解決問題。
由于存在b數(shù)組的操作,首先是區(qū)間翻轉(zhuǎn)可以懶標(biāo)記解決。
對(duì)于貢獻(xiàn)來說我們同樣記錄每個(gè)區(qū)間的最值,并且記錄一下最值出現(xiàn)位置pos\text {pos}pos的bposb_{\text{pos}}bpos?值,然后calc過程中記錄一個(gè)pre即可實(shí)現(xiàn)遞歸。
注意引用的巧妙使用!!!
由于引用不難知道:
int calc(int u,int &mx,int &pre)中的mx\text{mx}mx和pre\text{pre}pre始終表示當(dāng)前考慮的子序列最后一個(gè)值和最后一個(gè)值的b
#include<bits/stdc++.h>
using namespace std
;
using ll
=long long;
template <class T=int> T
rd()
{T res
=0;T fg
=1;char ch
=getchar();while(!isdigit(ch
)) {if(ch
=='-') fg
=-1;ch
=getchar();}while( isdigit(ch
)) res
=(res
<<1)+(res
<<3)+(ch
^48),ch
=getchar();return res
*fg
;
}
const int N
=200010;
int a
[N
],b
[N
],n
,m
;
struct node
{int l
,r
;int v
,cnt
;int bt
,tag
;
}tree
[N
<<2];
void pushdown(int u
)
{if(!tree
[u
].tag
) return;tree
[u
<<1].tag
^=1;tree
[u
<<1|1].tag
^=1;tree
[u
<<1].bt
^=1;tree
[u
<<1|1].bt
^=1;tree
[u
].tag
=0;
}
int calc(int u
,int &mx
,int &pre
)
{if(tree
[u
].v
<mx
) return 0;if(tree
[u
].l
==tree
[u
].r
){if(tree
[u
].v
>=mx
) {int ans
=(tree
[u
].bt
!=pre
); mx
=tree
[u
].v
,pre
=tree
[u
].bt
;return ans
;}return 0;}pushdown(u
);if(tree
[u
<<1].v
<mx
) return calc(u
<<1|1,mx
,pre
);int ans
=calc(u
<<1,mx
,pre
)+tree
[u
].cnt
-tree
[u
<<1].cnt
;mx
=tree
[u
].v
,pre
=tree
[u
].bt
;return ans
;}
void pushup(int u
)
{if(tree
[u
<<1].v
>tree
[u
<<1|1].v
)tree
[u
].v
=tree
[u
<<1].v
,tree
[u
].bt
=tree
[u
<<1].bt
;elsetree
[u
].v
=tree
[u
<<1|1].v
,tree
[u
].bt
=tree
[u
<<1|1].bt
;int mx
=tree
[u
<<1].v
,pre
=tree
[u
<<1].bt
;tree
[u
].cnt
=tree
[u
<<1].cnt
+calc(u
<<1|1,mx
,pre
);
}
void build(int u
,int l
,int r
)
{tree
[u
]={l
,r
};if(l
==r
){tree
[u
].v
=a
[l
];tree
[u
].bt
=b
[l
];tree
[u
].cnt
=1;return;}int mid
=l
+r
>>1;build(u
<<1,l
,mid
),build(u
<<1|1,mid
+1,r
);pushup(u
);
}
void change(int u
,int pos
,int v
)
{if(tree
[u
].l
==tree
[u
].r
) return tree
[u
].v
=v
,void();pushdown(u
);int mid
=tree
[u
].l
+tree
[u
].r
>>1;if(pos
<=mid
) change(u
<<1,pos
,v
);elsechange(u
<<1|1,pos
,v
);pushup(u
);
}
void filp(int u
,int l
,int r
)
{if(l
<=tree
[u
].l
&&tree
[u
].r
<=r
){tree
[u
].bt
^=1;tree
[u
].tag
^=1;return;}pushdown(u
);int mid
=tree
[u
].l
+tree
[u
].r
>>1;if(l
<=mid
) filp(u
<<1,l
,r
);if(r
>mid
)filp(u
<<1|1,l
,r
);pushup(u
);
}
int query(int u
,int l
,int r
,int &mx
,int &pre
)
{if(l
<=tree
[u
].l
&&tree
[u
].r
<=r
) return calc(u
,mx
,pre
);pushdown(u
);int mid
=tree
[u
].l
+tree
[u
].r
>>1;int v
=0;if(l
<=mid
) v
+=query(u
<<1,l
,r
,mx
,pre
);if(r
>mid
)v
+=query(u
<<1|1,l
,r
,mx
,pre
);return v
;
}
int main()
{n
=rd();for(int i
=1;i
<=n
;i
++) a
[i
]=rd();for(int i
=1;i
<=n
;i
++) b
[i
]=rd();build(1,1,n
);m
=rd();while(m
--){int op
=rd(),t1
=rd(),t2
=rd();if(op
==1) change(1,t1
,t2
);else if(op
==2) filp(1,t1
,t2
);else{int mx
=-1,pre
=-1;printf("%d\n",query(1,t1
,t2
,mx
,pre
)-1);}}return 0;
}
總結(jié)
以上是生活随笔為你收集整理的2021牛客暑期多校训练营7 B-xay loves monotonicity(线段树+不降子序列)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。