傳送門
此題是道好題!
首先要跳出思維定勢,不是去想如何用資料結構去直接維護排序過程,而是嘗試二分a[p]的值
設二分a[p]的值為x
我們將大於x的數標記為1,小於等於x的數標記為0
則整個序列只由01組成,記為b
將乙個區間公升序排序,則相當於將1全部移到右邊,0全部移到左邊,降序排序反之
例: a=.x=4
標記後的序列b為
此時對[1,5]進行公升序排序,a=
標記後的序列b為
因此可以用線段樹維護標記後的序列,直接區間求和得到1的個數,再區間更新即可
如果排完序後b[p]=0,則說明a[p]<=x,繼續減小x
否則增大x
#include
#include
#include
#include
#define maxn 100005
using namespace std;
int n,m,qa;
struct node
} tree[maxn<<2];
int a[maxn];
struct sort_seg q[maxn];
void push_up(int
pos)
void build(int l,int r,int
pos,int middle)
int mid=(tree[pos].l+tree[pos].r)>>1;
build(l,mid,pos
<<1,middle);
build(mid+1,r,pos
<<1|1, middle);
push_up(pos);
}void push_down(int
pos)
}void update(int l,int r,int v,int
pos)
push_down(pos);
int mid=(tree[pos].l+tree[pos].r)>>1;
if(l<=mid) update(l,r,v,pos
<<1);
if(r>mid) update(l,r,v,pos
<<1|1);
push_up(pos);
}int query(int l,int r,int
pos)
push_down(pos);
int mid=(tree[pos].l+tree[pos].r)>>1;
int ans=0;
if(l<=mid) ans+=query(l,r,pos
<<1);
if(r>mid) ans+=query(l,r,pos
<<1|1);
return ans;
}int check(int
x) else
}if(query(qa,qa,1)==1) return
0; else
return1;}
int main()
for(int i=1; i<=m; i++)
int l=1,r=n;
int ans=n+1;
scanf("%d",&qa);
while(l<=r) else
}printf("%d\n",ans);
}
bzoj4552排序(線段樹,二分)
題目大意 給定乙個長度為n的序列,有m個操作,操作包括兩種 0l r 0lr 區間 l,r 的數字公升序排序 1l r 1lr 區間 l,r 的數字降序排序 最後詢問在q位置上的數是多少?其中n 100000,m 100000 n 100000,m 100000 qwq這個題是看了題解才會的,感覺思...
b vj K th Number(二分 線段樹)
有乙個數列a 1 n 中 數字各不相同 輸入m行i,j,k,目的是求a i.j 之間第k小的數 includeusing namespace std typedef long long ll const int n 1e6 5 ll n,m,a n vectort n void pushup int...
hdu4614 二分 線段樹
題意 給你1 n的花瓶 剛開始全是空的,現在有兩種操作,1 從花瓶a開始插入b朵花 如果不能插進去 輸出字串 否則輸出最多插入的起點和終點 結構體陣列num i 表示節點i空瓶的數目 線段樹 開始deal函式對整個樹初始化,update 更新函式 find 查詢區間有多少個空瓶 對於操作1 關鍵點是...