→题目链接←
【想说的话】
期中考试gg了...
写发水题压压惊
【题解】
用两个数组,一个按分数从小到大排序,一个按价格从小到大排序
在按分数排序的数组上进行二分,把它当作中位数,然后在另一个数组中扫一遍找到两边的数,判断是否合法
复杂度O(nlogn)
[2018-10-21]:突然发现没有单调性,所以二分是假的,但是数据太弱了所以过了,还是优先队列吧...
【代码】
#include<bits/stdc++.h>
#define MAXN 100010
using namespace std;
inline int rd(){
int x=0,y=1;char c=getchar();
while(c<'0' || c>'9'){if(c=='-')y=-y;c=getchar();}
while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
return x*y;
}
struct node{
int val,cost;
int num;
};
bool cmp1(node a,node b){
return a.val<b.val;
}
bool cmp2(node a,node b){
return a.cost<b.cost;
}
int n,m,k;
node a[MAXN],b[MAXN];
bool check(int x){
if(x-1<n/2 || m-x<n/2)return false;
int sum=a[x].cost,tot1=0,tot2=0;
for(int i=1; i<=m; i++){
if(b[i].num==a[x].num)continue;
if(tot1<n/2 && b[i].val<=a[x].val)tot1++,sum+=b[i].cost;
else if(tot2<n/2 && b[i].val>=a[x].val)tot2++,sum+=b[i].cost;
if(sum>k)return false;
}
if(tot1<n/2 || tot2<n/2)return false;
return true;
}
int main(){
n=rd(),m=rd(),k=rd();
for(int i=1; i<=m; i++){
a[i].val=rd();
a[i].cost=rd();
a[i].num=i;
b[i]=a[i];
}
sort(a+1,a+m+1,cmp1);
sort(b+1,b+m+1,cmp2);
int l=1,r=m;
int ans=-1;
while(l<=r){
int mid=(l+r)/2;
if(check(mid))ans=a[mid].val,l=mid+1;
else r=mid-1;
}
printf("%d\n",ans);
return 0;
}