CF1837F Editorial for Two
//URL: https://www.luogu.com.cn/problem/CF1837F /* 6 5 4 1 10 1 1 1 5 3 1 20 5 15 3 5 3 1 20 3 15 5 10 6 10 8 20 14 3 8 6 4 16 11 10 5 9 9 2 13 15 19 4 9 13 12 1 1 1 2 6 5 21 18 1 */ /* 给定数字序列 问 求 k个 数字 组成的序列 可以 非连续 使得 max(前部分元素和,后部分元素)最小 二分显然 ->如何寻找 k个 数字 max(前部分元素和,后部分元素)最小 贪心:寻尽量小的 数字 既能满足 k个 又可以 数字和最小 ->如何寻找 前缀中 k个 最小值的 和 <== 优先队列 加入 若超过 mid 就pop top(max num) */ #pragma GCC optimize("O2") #pragma GCC optimize("Ofast") #pragma GCC optimize("inline") //牺牲编译速度+ 运行速度 #include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<string.h> #include<queue> #include<vector> #include<bits/stdc++.h> #define ll long long #define ddd printf("-----------------------\n"); using namespace std; const int maxn=3e5 +10; const int mod=998244353; const ll inf=0x3f3f3f3f3f3f3f3f; int a[maxn],f[maxn],ff[maxn],n,k; priority_queue<int> q; inline int read(){ int res=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar();} while(ch>='0'&&ch<='9'){ res=res*10+ch-'0'; ch=getchar();} return f*res; } bool ok(ll mid) { while(q.empty()==0) q.pop(); ll s=0; f[0]=0; for(int i=1;i<=n;i++) { s+=a[i]; q.push(a[i]); f[i]=f[i-1]+1; if(s>mid) f[i]--,s-=q.top(),q.pop(); } ff[n+1]=0,s=0; while(q.empty()==0) q.pop(); for(int i=n;i>=1;i--) { s+=a[i]; q.push(a[i]); ff[i]=ff[i+1]+1; if(s>mid) ff[i]--,s-=q.top(),q.pop(); } for(int i=0;i<n;i++) if(f[i]+ff[i+1]>=k) return 1; return 0; } int main() { // ios::sync_with_stdio(false); int T; T=read(); while(T--) { n=read(),k=read(); for(int i=1;i<=n;i++) a[i]=read(); ll l=1,r=inf; while(l<=r) { ll mid=l+r>>1; if(ok(mid)) r=mid-1; else l=mid+1; } //cout<<l<<'\n'; printf("%lld\n",l); } return 0; }