Range k-th Maximum Query-2020百度之星複賽
阿新 • • 發佈:2020-08-10
題意
題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=6840
分析:
最小等價於每個區間找第 \(l+1−k\) 小,然後使得和最小,和最大基本等價,所以我們考慮最大。最優方案中,假設 \(l=8,k=3\),那麼一定會這麼填 \(000001110000011100000111...\) 從大到小依次給這些位置 \(1\) 的位置填上數字。證明大概可以考慮如果我們放了前 \(a\) 大的,使得儘量多第 \(k\) 大的大於等於這個數的儘量多,那麼就等價於放 \(a\) 個 \(1\) ,使得不小於 \(k\) 個 \(1\) 的區間儘量多。
程式碼實現上,按段處理,每段長度為 \(l\)
程式碼:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+5; int a[N],n,l,k; bool cmp(int x,int y) { return x>y; } ll solve() { ll ans=0; int d=n/l; int r=n-d*l; for(int i=k;i<d*k;i++) { int p=n-i+1; if(i%k==0) ans+=1LL*(l-k+1)*a[p]; else ans+=a[p]; } ans+=1LL*(min(r+1,l-k+1))*a[n-d*k+1]; if(r>l-k) { for(int i=1;i<=r-(l-k);i++) ans+=a[n-k*d-i+1]; } return ans; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&l,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+1+n); ll ans=solve(); printf("%lld ",ans);//最大值 k=l-k+1;//第l-k+1小 sort(a+1,a+1+n,cmp);//按相反的順序 ans=solve(); printf("%lld\n",ans); } }