乙個長度為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...