絕世好題
首先對於求區間 \([l,r]\) 的中位數,有乙個套路可以套:
二分乙個值 \(d\) ,每次將區間內 \(的點設為 \(-1\) ,將 \(\ge d\) 的點設為 \(1\)。當區間和 \(\ge 0\) 時 \(d\) 值過大或剛好,若 \(<0\) 則 \(d\) 值過小。
我們繼續觀察題目。
我們發現,每次詢問的區間不固定,但是 \([b+1,c-1]\) 這個區間是必須選擇的,所以我們可以先求這個區間的和。
由於我們要最大化中位數,所以我們可以在 \([a,b]\) 中選取最大字尾,在 \([c,d]\) 中選取最大字首。
將三個區間的和加起來,就是我們要求的和了。
如果我們暴力統計查詢,單次查詢 \(o(nlog\ n)\) 顯然過不了,所以要想辦法優化。
我們可以對每乙個 \(d\) 建立一棵線段樹同時維護區間和、最大字首和、最大字尾和,下標維護元素位置。將 \(的點設為 \(-1\) ,將 \(\ge d\) 的點設為 \(1\),就可以區間查詢了。
但是這樣幹空間會炸,我們還要另想辦法。
將序列元素排序我們發現,對兩個相鄰的 \(d\) 值,其構造出來的 " \(1,-1\) " 序列只有一處不同。換句話說,它們的線段樹只有一條路徑不同。
我們可以考慮使用主席樹維護,將 \(d\) 所在位置的值改成 \(-1\) 即可,版本號依據 \(d\) 確定。
#include using namespace std;
const int n=2e5+10;
struct node
tree[n*60];
int root[n],tot=0,q[10];
int n,max;
int arr[n],v[n];
vectorpos[n];
#define lnode tree[node].lson
#define rnode tree[node].rson
#define defmid int mid=(start+end)>>1
void push_up(int node)
int build(int start,int end)
defmid;
lnode=build(start,mid);
rnode=build(mid+1,end);
push_up(node);
return node;
}#define lnode1 tree[node1].lson
#define rnode1 tree[node1].rson
int update(int node,int start,int end,int val)
defmid;
if(val<=mid) lnode1=update(lnode,start,mid,val);
else rnode1=update(rnode,mid+1,end,val);
push_up(node1);
return node1;
}int query1(int node,int start,int end,int l,int r)
int query2(int node,int start,int end,int l,int r)//最大字首和;
}int query3(int node,int start,int end,int l,int r)
}bool check(int mid)
int solve()
return l;
}int main()
sort(v+1,v+1+n);
max=unique(v+1,v+1+n)-v-1;
for(int i=1;i<=n;i++)
for(int i=1;i<=max;i++)//構建主席樹
int m,ans=0;
scanf("%d",&m);
for(int i=1;i<=m;i++)
return 0;
}
P2839 國家集訓隊 middle 解題報告
給乙個長度為 n nn 的序列。多次詢問,每次給出四個引數 a,b c,d a,b,c,d a,b,c,d 要求找乙個子區間 l,r l,r l,r 滿足 a l b,c r d a le l le b,c le r le d a l b,c r d,使得子區間的中位數最大。輸出中位數的最大值。首先...
P2839 國家集訓隊 middle
提一下靜態區間第k小的nlog2n的做法 1.建關於排名的主席樹 按排名順序建樹 2.二分答案。這樣做靜態區間第k小的雖然有些zz,但它的意義在於將線段樹 維護的物件改變了。1 include2 using namespace std 3int n,m,cnt 4int a 5 midd 5int ...
Luogu P2839 國家集訓隊 middle
首先 b,c 是必選的,然後選一段 a,b 的字尾和一段 c,d 的字首 都可空 對於中位數 這裡中位數採用這道題的定義 有個常見的處理方式 二分 mid,將 0,則說明 mid 的佔到了一半以上,即中位數 mid。採用這種處理方式,二分中位數,由於要中位數盡量大,所以要貪心,選字尾和字首使得大於等...