【問題描述】
定義乙個長度為奇數的區間的值為其所包含的的元素的中位數。
現給出n個數,求將所有長度為奇數的區間的值排序後,第k大的值為多少。
【輸入】
輸入檔名為kth.in。
第一行兩個數n和k
第二行,n個數。(0<=每個數<231)
【輸出】
輸出檔名為kth.out。
乙個數表示答案。
【輸入輸出樣例】
kth.in
kth.out
4 33 1 2 4
【樣例解釋】
[l,r]表示區間l~r的值
[1,1]:3
[2,2]:1
[3,3]:2
[4,4]:4
[1,3]:2
[2,4]:2
【資料說明】
對於30%的資料,1<=n<=100;
對於60%的資料,1<=n<=300
對於80%的資料,1<=n<=1000
對於100%的資料,1<=n<=100000, k<=奇數區間的數
分析:有點難想的一道題.
看到第k大,就應該想到要二分.二分x,接下來的任務就是找有多少個區間的值》=x.既然是中位數》=x,那麼比x大的數在區間中肯定佔了一半以上的數量,那麼開乙個陣列sum[i]表示1~i中有多少個數》=x.乙個區間只有2*(sum[r] - sum[l - 1]) > r - (l - 1).接下來就是常見的套路了,把結構相同的放在一起:2*sum[r] - r > 2*sum[l - 1] - (l - 1),換個元,另b[i] = 2*sum[i] - i,問題就轉化成了有多少個j滿足j < i && b[j] < b[i],樹狀陣列維護一遍就可以了.由於區間長度為奇數,所以要開兩個樹狀陣列分別記錄奇數和偶數的答案.
第k小/大用二分,式子一定要變形,相同結構放一起,換元之後再求解.
#include #include#include
#include
using
namespace
std;
typedef
long
long
ll;ll n, k, a[
100010], b[100010], l, r, ans, c[2][300010
];long
long
anss;
long
long
query(ll x, ll id)
return
res;
}void
add(ll x, ll id)
}ll cal(ll p)
for (int i = 0; i <= n; i++)
b[i] = 2 * b[i] - i + 100010
; anss = 0
;
for (int i = 0; i <= n; i++)
return
anss;
}int
main()
l = 0
;
while (l <=r)
else
r = mid - 1
; }
printf(
"%lld\n
", ans);
return0;
}
noip模擬賽 第K小數
問題描述 有兩個正整數數列,元素個數分別為n和m。從兩個數列中分別任取乙個數 相乘,這樣一共可以得到n m個數,詢問這n m個數中第k小數是多少。輸入格式 輸入檔名為number.in。輸入檔案包含三行。第一行為三個正整數n,m和k。第二行為n個正整數,表示第乙個數列。第三行為m個正整數,表述第二個...
51Nod 1686 第K大區間
題意 中文題,定義乙個區間的值為其眾數出現的次數。現給出n個數,求將所有區間的值排序後,第k大的值為多少。離散化二分答案加尺取判斷 include include includeusing namespace std const int maxn 100006 typedef long long l...
51nod 1686 第K大區間
1686 第k大區間 基準時間限制 1 秒 空間限制 131072 kb 分值 40 難度 4級演算法題 定義乙個區間的值為其眾數出現的次數。現給出n個數,求將所有區間的值排序後,第k大的值為多少。input 第一行兩個數n和k 1 n 100000,k n n 1 2 第二行n個數,0 每個數 2...