生活随笔
收集整理的這篇文章主要介紹了
2021牛客暑期多校训练营7 xay loves monotonicity 线段树区间合并
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
傳送門
文章目錄
題意:
題面挺繞口的,還是看原題比較好。
大概的意思就是讓你從給定的區(qū)間中選擇一個(gè)以左端點(diǎn)為起點(diǎn)的一個(gè)上升子序列,讓后將這些下標(biāo)存下來,在bbb中將這些位置拿出來后,如果相鄰一對(duì)在模222的意義下不相同貢獻(xiàn)就加一。
有三個(gè)操作,第一個(gè)是修改aaa數(shù)組,第二個(gè)是將bbb數(shù)組中[l,r][l,r][l,r]的位置都+1+1+1,第三個(gè)是詢問[l,r][l,r][l,r]的上述過程的貢獻(xiàn)。
思路:
比較明顯的要用線段樹區(qū)間合并來寫,之前寫過一個(gè)求全局的題樓房重建,這個(gè)題的重點(diǎn)就是calccalccalc函數(shù),我們需要魔改一下他的函數(shù)實(shí)現(xiàn)即可。
先不考慮bbb數(shù)組的貢獻(xiàn),先考慮如何求以lll為起點(diǎn),[l,r][l,r][l,r]中的最長非嚴(yán)格上升序列長度。
考慮函數(shù)calc(u,mx)calc(u,mx)calc(u,mx)表示uuu這個(gè)子樹中最大值為mxmxmx的時(shí)候的答案,顯然如果左區(qū)間的最大值<mx<mx<mx的話,直接返回右區(qū)間即可。否則說明兩邊的區(qū)間都可能有貢獻(xiàn),首先需要將答案加上calc(L,mx)calc(L,mx)calc(L,mx),如果暴力計(jì)算的話,我們還需要加上calc(R,tr[L].mx)calc(R,tr[L].mx)calc(R,tr[L].mx),但是我們?cè)?span id="ze8trgl8bvbq" class="katex--inline">pushuppushuppushup過程中可以記一個(gè)lenlenlen,代表當(dāng)前區(qū)間的答案,就是以當(dāng)前區(qū)間左端點(diǎn)為起點(diǎn)的最長上升子序列長度。這個(gè)時(shí)候calc(R,tr[L].mx)=tr[u].len?tr[L].lencalc(R,tr[L].mx)=tr[u].len-tr[L].lencalc(R,tr[L].mx)=tr[u].len?tr[L].len,這是為什么呢?可以發(fā)現(xiàn)不管calc(L,mx)calc(L,mx)calc(L,mx)計(jì)算的是多少,我們左區(qū)間選的最后一個(gè)數(shù)一定是左區(qū)間最大值,而我們的tr[u].len=tr[L].len+calc(R,tr[L].mx)tr[u].len=tr[L].len+calc(R,tr[L].mx)tr[u].len=tr[L].len+calc(R,tr[L].mx),所以直接移項(xiàng)即可。
這個(gè)時(shí)候已經(jīng)成功一大半了,我們只需要在calccalccalc函數(shù)中計(jì)算一下bbb數(shù)組的貢獻(xiàn)即可。所以維護(hù)一個(gè)flagflagflag表示當(dāng)前區(qū)間的最后一個(gè)位置的bbb是多少,讓后在calccalccalc函數(shù)到底的時(shí)候計(jì)算貢獻(xiàn)即可,這個(gè)就比較簡(jiǎn)單了。
沒做出來這個(gè)題還是對(duì)之前哪個(gè)題的calccalccalc函數(shù)有點(diǎn)誤解,不然也不會(huì)被卡在怎么查詢的問題上。或者是自己實(shí)現(xiàn)能力太差了,沒想到可以直接引用參數(shù)讓后在calccalccalc函數(shù)里面就可以修改。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#include<random>
#include<cassert>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid ((tr[u].l+tr[u].r)>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
<int,int> PII
;const int N
=1000010,mod
=1e9+7,INF
=0x3f3f3f3f;
const double eps
=1e-6;int n
,m
;
int a
[N
],b
[N
];
struct Node {int l
,r
;int mx
,cnt
,flag
,lazy
;
}tr
[N
<<2];void pushdown(int u
) {if(tr
[u
].lazy
) {tr
[L
].flag
^=1; tr
[L
].lazy
^=1;tr
[R
].flag
^=1; tr
[R
].lazy
^=1;tr
[u
].lazy
=0;}
}int query(int u
,int &mx
,int &flag
) {if(tr
[u
].l
==tr
[u
].r
) {if(tr
[u
].mx
>=mx
) {int now
=flag
!=tr
[u
].flag
;if(mx
==-1) now
=0;mx
=tr
[u
].mx
;flag
=tr
[u
].flag
;return now
;}return 0;}int ans
=0;pushdown(u
);if(tr
[L
].mx
>=mx
) {ans
=query(L
,mx
,flag
)+tr
[u
].cnt
-tr
[L
].cnt
;mx
=tr
[u
].mx
; flag
=tr
[u
].flag
;return ans
;} else return query(R
,mx
,flag
);
}void pushup(int u
) {tr
[u
].mx
=tr
[L
].mx
; tr
[u
].flag
=tr
[L
].flag
;tr
[u
].cnt
=tr
[L
].cnt
+query(R
,tr
[u
].mx
,tr
[u
].flag
);
}void build(int u
,int l
,int r
) {tr
[u
]={l
,r
};if(l
==r
) {tr
[u
].mx
=a
[l
]; tr
[u
].flag
=b
[l
];return;}build(L
,l
,Mid
); build(R
,Mid
+1,r
);pushup(u
);
}void change(int u
,int pos
,int x
) {if(tr
[u
].l
==tr
[u
].r
) {tr
[u
].mx
=x
;return;}pushdown(u
);if(pos
<=Mid
) change(L
,pos
,x
);else change(R
,pos
,x
);pushup(u
);
}void filp(int u
,int l
,int r
) {if(tr
[u
].l
>=l
&&tr
[u
].r
<=r
) {tr
[u
].lazy
^=1; tr
[u
].flag
^=1;return;}pushdown(u
);if(l
<=Mid
) filp(L
,l
,r
);if(r
>Mid
) filp(R
,l
,r
);pushup(u
);
}int aquery(int u
,int l
,int r
,int &mx
,int &flag
) {if(tr
[u
].l
>=l
&&tr
[u
].r
<=r
) return query(u
,mx
,flag
);pushdown(u
);int ans
=0;if(l
<=Mid
) ans
+=aquery(L
,l
,r
,mx
,flag
);if(r
>Mid
) ans
+=aquery(R
,l
,r
,mx
,flag
);return ans
;
}int main()
{
scanf("%d",&n
);for(int i
=1;i
<=n
;i
++) scanf("%d",&a
[i
]);for(int i
=1;i
<=n
;i
++) scanf("%d",&b
[i
]);build(1,1,n
);scanf("%d",&m
);while(m
--) {int op
,t1
,t2
;scanf("%d%d%d",&op
,&t1
,&t2
);if(op
==1) change(1,t1
,t2
);else if(op
==2) filp(1,t1
,t2
);else {int mx
=-1,flag
=0;printf("%d\n",aquery(1,t1
,t2
,mx
,flag
));}}return 0;
}
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)
總結(jié)
以上是生活随笔為你收集整理的2021牛客暑期多校训练营7 xay loves monotonicity 线段树区间合并的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。