BZOJ 2653 middle 二分 主席樹

2021-08-21 23:45:32 字數 1202 閱讀 2214

乙個長度為n的序列a,設其排過序之後為b,其中位數定義為b[n/2],其中a,b從0開始標號,除法取下整。給你乙個

長度為n的序列s。回答q個這樣的詢問:s的左端點在[a,b]之間,右端點在[c,d]之間的子串行中,最大的中位數。

第一行序列長度n。接下來n行按順序給出a中的數。

接下來一行q。然後q行每行a,b,c,d,我們令上個詢問的答案是

x(如果這是第乙個詢問則x=0)。

令陣列q=。

將q從小到大排序之後,令真正的

要詢問的a=q[0],b=q[1],c=q[2],d=q[3]。  

輸入保證滿足條件。

第一行所謂「排過序」指的是從小到大排序!

n<=20000,q<=25000

q行依次給出詢問的答案。

思路:

對於每次詢問,二分乙個答案,判斷是否可行。若大於等於這個數字

的位置標為1,否則標為0,即查詢a~b的右連續子區間加上b+1~c-1 的整段區間,在加上c~d的左連續區間的最大值

是否大於等於0。可以用主席樹維護每乙個狀態的0和1的資訊。

**:#includeusing namespace std;

const int maxn=20005;

struct node

c[maxn];

int l[maxn*20],r[maxn*20],sum[maxn*20],ls[maxn*20],rs[maxn*20];

bool cmp(const node &a,const node &b)

int query2(int rt,int ll,int rr,int l,int r)

int query3(int rt,int ll,int rr,int l,int r)

bool check(int x,int a,int b,int c,int d)

int main()

sort(c+1,c+n+1,cmp);

t[1]=build(1,n);

for(int i=2;i<=n;i++)

t[i]=update(t[i-1],1,n,c[i-1].id);

int x=0;

scanf("%d",&q);

while(q--)

printf("%d\n",x=c[i].v);

} return 0;

}

bzoj2653 Middle 二分 主席樹

這題厲害啊。根本想不到。據說是clj的題?首先要想到二分答案,想到就解出一半了。假設有乙個值x,如果x是區間 l,r 的中位數,且l a,b r c,d 那麼答案一定 x 否則答案一定 那麼如何判斷x是否是 l,r 的中位數呢?實際上,如果使用二分的話,我們不需要知道x是否一定是 l,r 的中位數,...

BZOJ2653 middle 主席樹 二分

無法確定中位數 我們可以考慮轉化思路。二分乙個中位數,再判斷是否合理。根據本題中中位數的定義,只需要小於 它的 數的個數 l en2 le 2len 我們可以將大於i ii的數賦值成1 11,小於的賦值成 1 1 1。若ma xlsu m a,b 1 sum b,c ma xrsu m c 1,d ...

bzoj2653 二分 主席樹

對於每乙個詢問二分答案。設當前答案為x,將 x的數的權值設為1,當 b 1,c 1 的權值和 a,b 權值和最大的字尾 c,d 權值和最大的字首 0時x可行。先對每個數離散,然後以每個值建立主席樹記錄區間和 最大字首 最大字尾就可以了。時間複雜度 o n log3n 1 include2 inclu...