bzoj4552排序(線段樹,二分)

2021-08-20 11:08:26 字數 2145 閱讀 1329

題目大意

給定乙個長度為n的序列,有m個操作,操作包括兩種: 0l

r 0lr

區間[l,r]的數字公升序排序 1l

r 1lr

區間[l,r]的數字降序排序

最後詢問在q位置上的數是多少?其中n

≤100000,m

≤100000

n

≤100000,m

≤100000

qwq這個題是看了題解才會的,感覺思路很不錯

我們考慮,這個題的詢問其實只有一組,所以我們可以 二分乙個最終在q的數是多少(或者說在原來的排名是多少)

每次將大於等於mi

d mid

的數變為1,小於的為0。

那麼對於公升序排序,假設這個區間有to

t tot

個1,

我們就可以將[r

−tot

+1,r

] [r−

tot+

1,r]

賦值為1,將剩餘區間賦值為0

而降序排序呢,我們就可以將[l

,l+t

ot−1

] [l,

l+to

t−1]

賦值為1,其餘為0

這樣就將「排序「 —->「區間賦值」:

那麼,我們不難想到!!!線段樹!!!

只需要最後我們看一下第q個數是不是1就可以,如果是1,我們可以稍微加大mid,不然就減少mid

上**

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

inline

int read()

while (isdigit(ch))

return x*f;

}const

int maxn = 100100;

int f[4*maxn];

int add[4*maxn];

int n,m,a[maxn];

int x[maxn],y[maxn],z[maxn];

int c[maxn];

int l,r;

int ques;

void up(int root)

void pushdown(int root,int l,int r)

}void build(int root,int l,int r)

int mid =(l+r) >> 1;

build(2*root,l,mid);

build(2*root+1,mid+1,r);

up(root);

}void update(int root,int l,int r,int x,int y,int p)

pushdown(root,l,r);

int mid = (l+r) >> 1;

if (x<=mid) update(2*root,l,mid,x,y,p);

if (y>mid) update(2*root+1,mid+1,r,x,y,p);

up(root);

}int query(int root,int l,int r,int x,int y)

pushdown(root,l,r);

int mid = (l+r) >> 1;

int ans=0;

if (x<=mid) ans=ans+query(2*root,l,mid,x,y);

if (y>mid) ans=ans+query(2*root+1,mid+1,r,x,y);

return ans;

}bool check(int mid)

else

}if (query(1,1,n,ques,ques)==1) return

true;

else

false;

}int ans;

int main()

ques=read();

//二分這個位置上的數是多少

while (l<=r)

cout

0;}

BZOJ 4552 二分 線段樹 思維)

傳送門 此題是道好題!首先要跳出思維定勢,不是去想如何用資料結構去直接維護排序過程,而是嘗試二分a p 的值 設二分a p 的值為x 我們將大於x的數標記為1,小於等於x的數標記為0 則整個序列只由01組成,記為b 將乙個區間公升序排序,則相當於將1全部移到右邊,0全部移到左邊,降序排序反之 例 a...

二分排序(java)

基本思想就是 將待排序元素分成大小大致相同 的兩個子集合,分別 對兩個子集合進行排序,最終將排好序的子集合合併成所要求的排好序的集合。package com.suanfa 二分排序 author administrator public class merge 合併陣列 public void co...

演算法 二分排序

二分排序這個詞是我在面試中遇到的,當時第一反應是二分查詢,然後被打斷,是二分排序演算法,最終才了解到,二分排序就是我們熟知的歸併排序。它又稱二路排序。首先說一下歸併的思想 先將一組數列,數列中含有n個元素,假設將每乙個元素看成是乙個有序的數列,就是n個有序的子串行,每個子串行的長度為1,然後倆倆合併...