雜題集萃[2]
阿新 • • 發佈:2018-09-15
include 偶數 () i++ main 表示 ans 得到 clu
中位數
題目描述
小N得到了一個非常神奇的序列A。
這個序列長度為N,下標從1開始。
A的一個子區間對應一個序列,可以由數對[l,r]表示,代表A[l], A[l + 1], ..., A[r]這段數。
對於一個序列B[1], B[2], ..., B[k],定義B的中位數如下:
先對B排序。得到新的序列C。
假如k是奇數,那麽中位數為。假如k為偶數,中位數為。
對於A的所有的子區間,小N可以知道它們對應的中位數。
現在小N想知道,所有長度>=Len的子區間中,中位數最大可以是多少。
輸入描述:
第一行輸入兩個數N,Len。
第二行輸入序列A,第i個數代表A[i]。
輸出描述:
一行一個整數,代表所有長度>=Len的子區間中,最大的中位數。
輸入
11 3
4864 8684 9511 8557 1122 1234 953 9819 101 1137 1759
輸出
8684
數據範圍:
30%: n <= 200
60%: n <= 2000
另外有20%:不超過50個不同的數
100%:1<=Len<=n<=10^5, 1 <= a[i] <= 10^9
題解
二分前綴和
code
#include<iostream> #include<cstdio> using namespace std; const int N=100010; int n,m,i,j,k,a[N],b[N],t,l,r,mid; bool f(int k){ for (int i=1;i<=n;i++) if (a[i]<k) b[i]=-1; else b[i]=1; for (int i=1;i<=n;i++) b[i]+=b[i-1]; int ans=b[m];t=0; for (int i=m+1;i<=n;i++){ t=min(t,b[i-m]); ans=max(ans,b[i]-t); } if (ans>0) return true; else return false; } int main(){ scanf("%d%d",&n,&m); for (i=1;i<=n;i++) scanf("%d",&a[i]); l=1;r=1000000000;while (l<r){ mid=(l+r)/2+1; if (f(mid)) l=mid; else r=mid-1; } printf("%d\n",l); return 0; }
雜題集萃[2]