题目传送门
首先这道题不可二分,自己YY一下挺显然的。
把每个人按照成绩排序,从大往小扫,用三个可删除的堆 q 1 , q 2 , q 3 q1,q2,q3 q1,q2,q3维护。 q 1 , q 3 q1,q3 q1,q3分别维护当前位置左右的前 k k k大, q 2 q2 q2维护左边不是前 k k k大的,相当于 q 1 q1 q1的后备。
具体实现见代码:
#include
#include
#include
#include
#include
#define N 200005
#define F inline
using namespace std;
typedef long long LL;
struct data{ int x; LL w; }a[N];
struct Q{
priority_queue<LL> q,d;
F void push(LL x){ q.push(x); }
F void erase(LL x){ d.push(x); }
F LL top(){
while (!d.empty()&&q.top()==d.top())
q.pop(),d.pop(); return q.top();
}
F void pop(){
while (!d.empty()&&q.top()==d.top())
q.pop(),d.pop(); q.pop();
}
F LL size(){ return q.size()-d.size(); }
}q1,q2,q3;
int c,n; LL f,s1,s2;
F char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
return l==r?EOF:*l++;
}
F int _read(){
int x=0; char ch=readc();
while (!isdigit(ch)) ch=readc();
while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
return x;
}
F bool cmp1(data a,data b){ return a.w<b.w; }
F bool cmp2(data a,data b){ return a.x<b.x; }
F int pd(){
for (int i=1;i<n-c/2;i++){
if (q1.size()<c/2) q1.push(a[i].w),s1+=a[i].w;
else if (q1.top()>a[i].w)
q2.push(-q1.top()),s1-=q1.top()-a[i].w,q1.pop(),q1.push(a[i].w);
else q2.push(-a[i].w);
}
for (int i=n-c/2+1;i<=n;i++) q3.push(a[i].w),s2+=a[i].w;
for (int i=n-c/2;i>c/2;i--){
if (s1+s2+a[i].w<=f) return i;
if (q3.top()>a[i].w) s2+=a[i].w-q3.top(),q3.pop(),q3.push(a[i].w);
if (q1.top()<a[i-1].w) q2.erase(-a[i-1].w);
else q1.erase(a[i-1].w),q1.push(-q2.top()),s1-=q2.top()+a[i-1].w,q2.pop();
}
}
int main(){
c=_read(),n=_read(),f=_read();
for (int i=1;i<=n;i++) a[i].x=_read(),a[i].w=_read();
sort(a+1,a+n+1,cmp1);
for (LL i=1,s=0;i<=c;i++)
if ((s+=a[i].w)>f) return puts("-1"),0;
sort(a+1,a+n+1,cmp2);
return printf("%d\n",a[pd()].x),0;
}