日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

2021牛客暑期多校训练营7 B-xay loves monotonicity(线段树+不降子序列)

發布時間:2023/12/3 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2021牛客暑期多校训练营7 B-xay loves monotonicity(线段树+不降子序列) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

P4198 樓房重建
線段樹維護以某點為開頭的最長不下降子序列

使用下面calc函數能夠計算線段樹u維護的區間中,以x為開頭最長不下降子序列的個數。

calc需要維護區間最值。

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數組,就是上面的樓房重建,用上面calc函數遞歸解決問題。

由于存在b數組的操作,首先是區間翻轉可以懶標記解決。
對于貢獻來說我們同樣記錄每個區間的最值,并且記錄一下最值出現位置pos\text {pos}posbposb_{\text{pos}}bpos?值,然后calc過程中記錄一個pre即可實現遞歸。

注意引用的巧妙使用!!!

由于引用不難知道:
int calc(int u,int &mx,int &pre)中的mx\text{mx}mxpre\text{pre}pre始終表示當前考慮的子序列最后一個值和最后一個值的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;// 區間最值v 以左端點為起點的最長不下降子序列int bt,tag;// 區間最值位置的b值 懶標記 }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)//在子樹u中以mx為起點的貢獻,pre為mx位置的b的值 {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); // 貢獻需要和前一個b不一樣mx=tree[u].v,pre=tree[u].bt;// 修改mx和prereturn 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)// 區間最值和最值出現位置的b(靠右邊)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);// -1表示刪去計算上序列一個值的貢獻}}return 0; }

總結

以上是生活随笔為你收集整理的2021牛客暑期多校训练营7 B-xay loves monotonicity(线段树+不降子序列)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。