乍一看這道題跟cf558e長得非常像,我們能否採用解決這道題的方法來解決這道題呢?
答案:不行。
cf558e那道題排序過程之所以能用線段樹維護是因為排序的值域是確定的,只有26,因此我們暴力開26棵線段樹維護狀態沒有問題。但是這道題顯然就不行了,值域為n,我們開不下。
這時我們的思路就向cf558e那道題的思路去靠近,我們能否通過一些特殊的手段來限制值域從而是排序過程變得可以維護呢?
最簡單的值域:0/1
由於查詢只有一次,我們想到這裡之後就感覺這道題變得可做了起來。
我們考慮如何將幾個數的值域變成0/1----->二分答案。
二分列舉最終位置的數是否能夠》=x。
過程中將大於等於x的數變成1,小於x的數變成0。
於是問題就變成了0/1的排序,這樣問題就變得比cf558e簡單多了。
是否滿足條件只需要看那個位置的數是否為1即可。
中間用線段樹維護,具體過程不講了。
二分答案不斷放縮的過程中,我們可以得到最終答案。
#include
using
namespace std;
const
int n =
2e5+
100;
int n,m,po;
int a[n]
;struct nodeq[n]
;struct trtr[
4*n]
;void
spread
(int x,
int l,
int r)
void
change
(int x,
int l,
int r,
int l,
int r,
int v)
spread
(x,l,r)
;int mid = l+r>>1;
if(l <= mid)
change
(x<<
1,l,mid,l,r,v);if
(r > mid)
change
(x<<1|
1,mid+
1,r,l,r,v)
; tr[x]
.val = tr[x<<1]
.val + tr[x<<1|
1].val;
}int
ask(
int x,
int l,
int r,
int l,
int r)
spread
(x,l,r)
;int mid = l+r>>1;
int sum =0;
if(l <= mid) sum+
=ask
(x<<
1,l,mid,l,r);if
(r > mid) sum+
=ask
(x<<1|
1,mid+
1,r,l,r)
;return sum;
}}tr;
bool
check
(int x)
else
// for (int i = 1; i <= n; i++) cout<<"i = "<}
// for (int i = 1; i <= n; i++) cout<<"i = "ask(1,
1,n,po,po)==1
;}intmain()
printf
("%d"
,check
(r)?r:l)
;return0;
}
luogu P2824排序 題解
heoi2016 tjoi 排序 在2016年,佳媛姐姐喜歡上了數字序列。因而他經常研究關於序列的一些奇奇怪怪的問題,現在他在研究乙個難題,需要你來幫助他。這個難題是這樣子的 給出乙個1到n的全排列,現在對這個全排列序列進行m次區域性排序,排序分為兩種 1 0,l,r 表示將區間 l,r 的數字公升...
洛谷P1347 排序
這個題看到很多人寫topo排序,其實這道題第一眼看更像是乙個差分約束的裸題qwq.令dis x 表示x的相對大小 1是最小,n是最大 顯然,對於乙個關係a 而我們最後要求的就是dis x 的最小值,為了使它們的值都落在1 n之間,我們新建乙個虛擬的點0,並令dis 0 0且dis x dis 0 這...
洛谷 P1347 排序 拓撲排序
題目 乙個不同的值的公升序排序數列指的是乙個從左到右元素依次增大的序列,例如,乙個有序的數列a,b,c,d 表示a第一行有兩個整數n,m,n表示需要排序的元素數量,2 n 26,第1到n個元素將用大寫的a,b,c,d 表示。m表示將給出的形如a接下來有m行,每行有3個字元,分別為乙個大寫字母,乙個 ...